コード例 #1
0
        public static bool TrainBankStatement(Int32 ALedgerNumber, DateTime ADateOfStatement, string ABankAccountCode)
        {
            // get the statement keys
            TDBTransaction ReadTransaction = DBAccess.GDBAccessObj.BeginTransaction(IsolationLevel.ReadCommitted);

            AEpStatementTable Statements = new AEpStatementTable();
            AEpStatementRow   row        = Statements.NewRowTyped(false);

            row.LedgerNumber    = ALedgerNumber;
            row.Date            = ADateOfStatement;
            row.BankAccountCode = ABankAccountCode;

            Statements = AEpStatementAccess.LoadUsingTemplate(row, ReadTransaction);

            DBAccess.GDBAccessObj.RollbackTransaction();

            if (Statements.Rows.Count == 0)
            {
                return(false);
            }

            // search for already posted gift batches, and do the matching for these imported statements
            TBankImportMatching.Train(Statements);

            return(true);
        }
コード例 #2
0
        public static AEpStatementTable GetImportedBankStatements(Int32 ALedgerNumber, DateTime AStartDate)
        {
            TDBTransaction ReadTransaction = DBAccess.GDBAccessObj.BeginTransaction(IsolationLevel.ReadCommitted);

            AEpStatementTable localTable = new AEpStatementTable();
            AEpStatementRow   row        = localTable.NewRowTyped(false);

            row.LedgerNumber = ALedgerNumber;
            row.Date         = AStartDate;

            StringCollection operators = new StringCollection();

            operators.Add("=");
            operators.Add(">=");

            localTable = AEpStatementAccess.LoadUsingTemplate(row, operators, null, ReadTransaction);

            DBAccess.GDBAccessObj.RollbackTransaction();

            return(localTable);
        }
        private void DeleteStatement(object sender, EventArgs e)
        {
            DataRowView[] SelectedGridRow = grdSelectStatement.SelectedDataRowsAsDataRowView;

            if (SelectedGridRow.Length >= 1)
            {
                AEpStatementRow toDelete = (AEpStatementRow)SelectedGridRow[0].Row;

                if (MessageBox.Show(
                        String.Format(Catalog.GetString("Do you really want to delete the bank statement {0}?"),
                                      toDelete.Filename),
                        Catalog.GetString("Confirmation"),
                        MessageBoxButtons.YesNo,
                        MessageBoxIcon.Question) == DialogResult.Yes)
                {
                    if (FPluginRemote.WebConnectors.DropBankStatement(toDelete.StatementKey))
                    {
                        PopulateStatementGrid(null, null);
                    }
                }
            }
        }
コード例 #4
0
ファイル: Matching.cs プロジェクト: TheBigBear/openpetra
        private static void CreateMatches(BankImportTDS AMainDS,
                                          AEpStatementRow ACurrentStatement,
                                          Int32 ASelectedGiftBatch, bool APostedBatch)
        {
            // remove all gifts and giftdetails that don't belong to the selected batch
            List <DataRow> ToDelete = new List <DataRow>();

            foreach (AGiftDetailRow giftdetail in AMainDS.AGiftDetail.Rows)
            {
                if (giftdetail.BatchNumber != ASelectedGiftBatch)
                {
                    ToDelete.Add(giftdetail);
                }
            }

            foreach (DataRow del in ToDelete)
            {
                AMainDS.AGiftDetail.Rows.Remove(del);
            }

            ToDelete = new List <DataRow>();

            foreach (AGiftRow gift in AMainDS.AGift.Rows)
            {
                if (gift.BatchNumber != ASelectedGiftBatch)
                {
                    ToDelete.Add(gift);
                }
            }

            foreach (DataRow del in ToDelete)
            {
                AMainDS.AGift.Rows.Remove(del);
            }

            ToDelete = new List <DataRow>();

            foreach (BankImportTDSAEpTransactionRow transaction  in AMainDS.AEpTransaction.Rows)
            {
                // delete transactions with negative amount
                if (transaction.TransactionAmount < 0)
                {
                    ToDelete.Add(transaction);
                }
                else
                {
                    transaction.MatchAction = MFinanceConstants.BANK_STMT_STATUS_UNMATCHED;
                }
            }

            foreach (DataRow del in ToDelete)
            {
                AMainDS.AEpTransaction.Rows.Remove(del);
            }

            FindDonorKeysByBankAccount(AMainDS);

            AMainDS.PBankingDetails.DefaultView.Sort = BankImportTDSPBankingDetailsTable.GetPartnerKeyDBName();

            MatchDonorsWithKnownBankaccount(AMainDS);

            while (MatchTransactionsToGiftBatch(AMainDS))
            {
                ;
            }

            if (TLogging.DebugLevel > 0)
            {
                TLogging.Log("transactions not matched yet:");

                foreach (BankImportTDSAEpTransactionRow transaction in AMainDS.AEpTransaction.Rows)
                {
                    if (transaction.MatchAction != Ict.Petra.Shared.MFinance.MFinanceConstants.BANK_STMT_STATUS_MATCHED)
                    {
                        TLogging.Log(
                            "  " + transaction.DonorKey.ToString() + " " + transaction.AccountName + " --- " + transaction.Description + " " +
                            transaction.TransactionAmount.ToString());

                        if (transaction.DonorKey == -1)
                        {
                            TLogging.Log("     " + transaction.BankAccountNumber + " " + transaction.BranchCode);
                        }
                    }
                }

                TLogging.Log("gifts not matched yet:");

                foreach (BankImportTDSAGiftDetailRow giftdetail in AMainDS.AGiftDetail.Rows)
                {
                    if (!giftdetail.AlreadyMatched)
                    {
                        string HasBankDetails   = "-";
                        int    BankDetailsIndex = AMainDS.PBankingDetails.DefaultView.Find(giftdetail.DonorKey);

                        if (BankDetailsIndex != -1)
                        {
                            HasBankDetails = "*";
                        }

                        TLogging.Log(
                            "  " + HasBankDetails + " " + giftdetail.DonorKey.ToString() + " " + giftdetail.DonorShortName + " --- " +
                            giftdetail.RecipientDescription + " " + giftdetail.GiftAmount.ToString());

                        if (BankDetailsIndex != -1)
                        {
                            BankImportTDSPBankingDetailsRow bankdetail =
                                (BankImportTDSPBankingDetailsRow)AMainDS.PBankingDetails.DefaultView[BankDetailsIndex].Row;
                            TLogging.Log("     " + bankdetail.BankAccountNumber + " " + bankdetail.BankSortCode);
                        }
                    }
                }

                int CountMatched = 0;

                foreach (BankImportTDSAEpTransactionRow transaction in AMainDS.AEpTransaction.Rows)
                {
                    if (transaction.MatchAction == Ict.Petra.Shared.MFinance.MFinanceConstants.BANK_STMT_STATUS_MATCHED)
                    {
                        CountMatched++;
                    }
                }

                TLogging.Log("matched: " + CountMatched.ToString() + " of " + AMainDS.AEpTransaction.Rows.Count.ToString());
            }

            StoreCurrentMatches(AMainDS, ACurrentStatement.BankAccountCode);
        }
コード例 #5
0
ファイル: Matching.cs プロジェクト: TheBigBear/openpetra
        /// <summary>
        /// there are several gift batches that might fit this bank statement. find the right one!
        /// simple matching; no split gifts, bank account number fits and amount fits
        /// </summary>
        private static int FindGiftBatch(BankImportTDS AMainDS, AEpStatementRow AStmt)
        {
            SortedList <Int32, Int32> MatchedGiftBatches = new SortedList <int, int>();

            // create the dataview only after loading, otherwise loading is much slower
            DataView GiftDetailByAmountAndDonor = new DataView(AMainDS.AGiftDetail,
                                                               string.Empty,
                                                               AGiftDetailTable.GetGiftAmountDBName() + "," +
                                                               BankImportTDSAGiftDetailTable.GetDonorKeyDBName(),
                                                               DataViewRowState.CurrentRows);

            DataView GiftByAmountAndDonor = new DataView(AMainDS.AGift,
                                                         string.Empty,
                                                         BankImportTDSAGiftTable.GetTotalAmountDBName() + "," +
                                                         AGiftTable.GetDonorKeyDBName(),
                                                         DataViewRowState.CurrentRows);

            AMainDS.PBankingDetails.DefaultView.Sort = BankImportTDSPBankingDetailsTable.GetBankSortCodeDBName() + "," +
                                                       BankImportTDSPBankingDetailsTable.GetBankAccountNumberDBName();

            foreach (BankImportTDSAEpTransactionRow transaction in AMainDS.AEpTransaction.Rows)
            {
                // find the donor for this transaction, by his bank account number
                Int64 DonorKey = GetDonorByBankAccountNumber(AMainDS, transaction.BranchCode, transaction.BankAccountNumber);

                if (transaction.BankAccountNumber.Length == 0)
                {
                    // useful for NUnit testing for csv import: partnerkey in description
                    try
                    {
                        DonorKey = Convert.ToInt64(transaction.Description);
                    }
                    catch (Exception)
                    {
                        DonorKey = -1;
                    }
                }

                BankImportTDSAGiftDetailRow detailrow = null;

                if (DonorKey != -1)
                {
                    DataRowView[] giftDetails = GiftDetailByAmountAndDonor.FindRows(new object[] { transaction.TransactionAmount, DonorKey });

                    if (giftDetails.Length == 1)
                    {
                        // found a possible match
                        detailrow = (BankImportTDSAGiftDetailRow)giftDetails[0].Row;
                    }
                    else
                    {
                        // check if we can find a gift with several gift details, that would match this transaction amount
                        DataRowView[] gifts = GiftByAmountAndDonor.FindRows(new object[] { transaction.TransactionAmount, DonorKey });

                        if (gifts.Length >= 1)
                        {
                            AGiftRow gift = (AGiftRow)gifts[0].Row;
                            detailrow =
                                (BankImportTDSAGiftDetailRow)AMainDS.AGiftDetail.Rows.Find(new object[] { gift.LedgerNumber, gift.BatchNumber,
                                                                                                          gift.GiftTransactionNumber,
                                                                                                          1 });
                        }
                    }
                }

                if (detailrow != null)
                {
                    if (MatchedGiftBatches.ContainsKey(detailrow.BatchNumber))
                    {
                        MatchedGiftBatches[detailrow.BatchNumber]++;
                    }
                    else
                    {
                        MatchedGiftBatches.Add(detailrow.BatchNumber, 1);
                    }
                }
            }

            int SelectedGiftBatch = -1;
            int maxMatches        = 0;

            foreach (int GiftBatchNumber in MatchedGiftBatches.Keys)
            {
                if (MatchedGiftBatches[GiftBatchNumber] > maxMatches)
                {
                    maxMatches        = MatchedGiftBatches[GiftBatchNumber];
                    SelectedGiftBatch = GiftBatchNumber;
                }
            }

            if ((SelectedGiftBatch != -1) &&
                ((AMainDS.AEpTransaction.Rows.Count > 2) &&
                 (MatchedGiftBatches[SelectedGiftBatch] < AMainDS.AEpTransaction.Rows.Count / 2)))
            {
                TLogging.Log(
                    "cannot find enough gifts that look the same, for statement " + AStmt.Filename +
                    ". CountMatches for batch " + SelectedGiftBatch.ToString() + ": " +
                    MatchedGiftBatches[SelectedGiftBatch].ToString());

                SelectedGiftBatch = -1;
            }

            return(SelectedGiftBatch);
        }
コード例 #6
0
        public static Int32 CreateGLBatch(BankImportTDS AMainDS,
                                          Int32 ALedgerNumber,
                                          Int32 AStatementKey,
                                          Int32 AGLBatchNumber,
                                          out TVerificationResultCollection AVerificationResult)
        {
            AMainDS.AEpTransaction.DefaultView.RowFilter =
                String.Format("{0}={1}",
                              AEpTransactionTable.GetStatementKeyDBName(),
                              AStatementKey);
            AMainDS.AEpStatement.DefaultView.RowFilter =
                String.Format("{0}={1}",
                              AEpStatementTable.GetStatementKeyDBName(),
                              AStatementKey);
            AEpStatementRow stmt = (AEpStatementRow)AMainDS.AEpStatement.DefaultView[0].Row;

            AVerificationResult = null;

            Int32          DateEffectivePeriodNumber, DateEffectiveYearNumber;
            TDBTransaction Transaction = DBAccess.GDBAccessObj.BeginTransaction(IsolationLevel.ReadCommitted);

            if (!TFinancialYear.IsValidPostingPeriod(ALedgerNumber, stmt.Date, out DateEffectivePeriodNumber, out DateEffectiveYearNumber,
                                                     Transaction))
            {
                string msg = String.Format(Catalog.GetString("Cannot create a GL batch for date {0} since it is not in an open period of the ledger."),
                                           stmt.Date.ToShortDateString());
                TLogging.Log(msg);
                AVerificationResult = new TVerificationResultCollection();
                AVerificationResult.Add(new TVerificationResult(Catalog.GetString("Creating GL Batch"), msg, TResultSeverity.Resv_Critical));

                DBAccess.GDBAccessObj.RollbackTransaction();
                return(-1);
            }

            Int32 BatchYear, BatchPeriod;

            // if DateEffective is outside the range of open periods, use the most fitting date
            DateTime DateEffective = stmt.Date;

            TFinancialYear.GetLedgerDatePostingPeriod(ALedgerNumber, ref DateEffective, out BatchYear, out BatchPeriod, Transaction, true);

            ALedgerTable LedgerTable = ALedgerAccess.LoadByPrimaryKey(ALedgerNumber, Transaction);

            DBAccess.GDBAccessObj.RollbackTransaction();

            GLBatchTDS GLDS = TGLTransactionWebConnector.CreateABatch(ALedgerNumber);

            ABatchRow glbatchRow = GLDS.ABatch[0];

            glbatchRow.BatchPeriod      = BatchPeriod;
            glbatchRow.DateEffective    = DateEffective;
            glbatchRow.BatchDescription = String.Format(Catalog.GetString("bank import for date {0}"), stmt.Date.ToShortDateString());

            decimal HashTotal   = 0.0M;
            decimal DebitTotal  = 0.0M;
            decimal CreditTotal = 0.0M;

            // TODO: support several journals
            // TODO: support several currencies, support other currencies than the base currency
            AJournalRow gljournalRow = GLDS.AJournal.NewRowTyped();

            gljournalRow.LedgerNumber        = glbatchRow.LedgerNumber;
            gljournalRow.BatchNumber         = glbatchRow.BatchNumber;
            gljournalRow.JournalNumber       = glbatchRow.LastJournal + 1;
            gljournalRow.TransactionCurrency = LedgerTable[0].BaseCurrency;
            glbatchRow.LastJournal++;
            gljournalRow.JournalPeriod       = glbatchRow.BatchPeriod;
            gljournalRow.DateEffective       = glbatchRow.DateEffective;
            gljournalRow.JournalDescription  = glbatchRow.BatchDescription;
            gljournalRow.SubSystemCode       = CommonAccountingSubSystemsEnum.GL.ToString();
            gljournalRow.TransactionTypeCode = CommonAccountingTransactionTypesEnum.STD.ToString();
            gljournalRow.ExchangeRateToBase  = 1.0m;
            GLDS.AJournal.Rows.Add(gljournalRow);

            foreach (DataRowView dv in AMainDS.AEpTransaction.DefaultView)
            {
                AEpTransactionRow transactionRow = (AEpTransactionRow)dv.Row;

                DataView v = AMainDS.AEpMatch.DefaultView;
                v.RowFilter = AEpMatchTable.GetActionDBName() + " = '" + MFinanceConstants.BANK_STMT_STATUS_MATCHED_GL + "' and " +
                              AEpMatchTable.GetMatchTextDBName() + " = '" + transactionRow.MatchText + "'";

                if (v.Count > 0)
                {
                    AEpMatchRow     match = (AEpMatchRow)v[0].Row;
                    ATransactionRow trans = GLDS.ATransaction.NewRowTyped();
                    trans.LedgerNumber      = glbatchRow.LedgerNumber;
                    trans.BatchNumber       = glbatchRow.BatchNumber;
                    trans.JournalNumber     = gljournalRow.JournalNumber;
                    trans.TransactionNumber = gljournalRow.LastTransactionNumber + 1;
                    trans.AccountCode       = match.AccountCode;
                    trans.CostCentreCode    = match.CostCentreCode;
                    trans.Reference         = match.Reference;
                    trans.Narrative         = match.Narrative;
                    trans.TransactionDate   = transactionRow.DateEffective;

                    if (transactionRow.TransactionAmount < 0)
                    {
                        trans.AmountInBaseCurrency = -1 * transactionRow.TransactionAmount;
                        trans.TransactionAmount    = -1 * transactionRow.TransactionAmount;
                        trans.DebitCreditIndicator = true;
                        DebitTotal += trans.AmountInBaseCurrency;
                    }
                    else
                    {
                        trans.AmountInBaseCurrency = transactionRow.TransactionAmount;
                        trans.TransactionAmount    = transactionRow.TransactionAmount;
                        trans.DebitCreditIndicator = false;
                        CreditTotal += trans.AmountInBaseCurrency;
                    }

                    GLDS.ATransaction.Rows.Add(trans);
                    gljournalRow.LastTransactionNumber++;

                    // add one transaction for the bank as well
                    trans = GLDS.ATransaction.NewRowTyped();
                    trans.LedgerNumber      = glbatchRow.LedgerNumber;
                    trans.BatchNumber       = glbatchRow.BatchNumber;
                    trans.JournalNumber     = gljournalRow.JournalNumber;
                    trans.TransactionNumber = gljournalRow.LastTransactionNumber + 1;
                    trans.AccountCode       = stmt.BankAccountCode;
                    trans.CostCentreCode    = TLedgerInfo.GetStandardCostCentre(ALedgerNumber);
                    trans.Reference         = match.Reference;
                    trans.Narrative         = match.Narrative;
                    trans.TransactionDate   = transactionRow.DateEffective;

                    if (transactionRow.TransactionAmount < 0)
                    {
                        trans.AmountInBaseCurrency = -1 * transactionRow.TransactionAmount;
                        trans.TransactionAmount    = -1 * transactionRow.TransactionAmount;
                        trans.DebitCreditIndicator = false;
                        CreditTotal += trans.AmountInBaseCurrency;
                    }
                    else
                    {
                        trans.AmountInBaseCurrency = transactionRow.TransactionAmount;
                        trans.TransactionAmount    = transactionRow.TransactionAmount;
                        trans.DebitCreditIndicator = true;
                        DebitTotal += trans.AmountInBaseCurrency;
                    }

                    GLDS.ATransaction.Rows.Add(trans);
                    gljournalRow.LastTransactionNumber++;
                }
            }

            gljournalRow.JournalDebitTotal  = DebitTotal;
            gljournalRow.JournalCreditTotal = CreditTotal;
            glbatchRow.BatchDebitTotal      = DebitTotal;
            glbatchRow.BatchCreditTotal     = CreditTotal;
            glbatchRow.BatchControlTotal    = HashTotal;

            TVerificationResultCollection VerificationResult;

            TSubmitChangesResult result = TGLTransactionWebConnector.SaveGLBatchTDS(ref GLDS,
                                                                                    out VerificationResult);

            if (result == TSubmitChangesResult.scrOK)
            {
                return(glbatchRow.BatchNumber);
            }

            TLogging.Log("Problems storing GL Batch");
            return(-1);
        }
コード例 #7
0
        public static Int32 CreateGiftBatch(
            Int32 ALedgerNumber,
            Int32 AStatementKey,
            Int32 AGiftBatchNumber,
            out TVerificationResultCollection AVerificationResult)
        {
            BankImportTDS MainDS = GetBankStatementTransactionsAndMatches(AStatementKey, ALedgerNumber);

            string MyClientID = DomainManager.GClientID.ToString();

            TProgressTracker.InitProgressTracker(MyClientID,
                                                 Catalog.GetString("Creating gift batch"),
                                                 MainDS.AEpTransaction.DefaultView.Count + 10);

            AVerificationResult = new TVerificationResultCollection();

            MainDS.AEpTransaction.DefaultView.RowFilter =
                String.Format("{0}={1}",
                              AEpTransactionTable.GetStatementKeyDBName(),
                              AStatementKey);
            MainDS.AEpStatement.DefaultView.RowFilter =
                String.Format("{0}={1}",
                              AEpStatementTable.GetStatementKeyDBName(),
                              AStatementKey);
            AEpStatementRow stmt = (AEpStatementRow)MainDS.AEpStatement.DefaultView[0].Row;

            // TODO: optional: use the preselected gift batch, AGiftBatchNumber

            Int32          DateEffectivePeriodNumber, DateEffectiveYearNumber;
            DateTime       BatchDateEffective = stmt.Date;
            TDBTransaction Transaction        = DBAccess.GDBAccessObj.BeginTransaction(IsolationLevel.ReadCommitted);

            if (!TFinancialYear.GetLedgerDatePostingPeriod(ALedgerNumber, ref BatchDateEffective, out DateEffectiveYearNumber,
                                                           out DateEffectivePeriodNumber,
                                                           Transaction, true))
            {
                // just use the latest possible date
                string msg =
                    String.Format(Catalog.GetString("Date {0} is not in an open period of the ledger, using date {1} instead for the gift batch."),
                                  stmt.Date.ToShortDateString(),
                                  BatchDateEffective.ToShortDateString());
                AVerificationResult.Add(new TVerificationResult(Catalog.GetString("Creating Gift Batch"), msg, TResultSeverity.Resv_Info));
            }

            ACostCentreAccess.LoadViaALedger(MainDS, ALedgerNumber, Transaction);
            AMotivationDetailAccess.LoadViaALedger(MainDS, ALedgerNumber, Transaction);

            MainDS.AEpMatch.DefaultView.Sort =
                AEpMatchTable.GetActionDBName() + ", " +
                AEpMatchTable.GetMatchTextDBName();

            if (MainDS.AEpTransaction.DefaultView.Count == 0)
            {
                AVerificationResult.Add(new TVerificationResult(
                                            Catalog.GetString("Creating Gift Batch"),
                                            String.Format(Catalog.GetString("There are no transactions for statement #{0}."), AStatementKey),
                                            TResultSeverity.Resv_Info));
                return(-1);
            }

            foreach (DataRowView dv in MainDS.AEpTransaction.DefaultView)
            {
                AEpTransactionRow transactionRow = (AEpTransactionRow)dv.Row;

                DataRowView[] matches = MainDS.AEpMatch.DefaultView.FindRows(new object[] {
                    MFinanceConstants.BANK_STMT_STATUS_MATCHED_GIFT,
                    transactionRow.MatchText
                });

                if (matches.Length > 0)
                {
                    AEpMatchRow match = (AEpMatchRow)matches[0].Row;

                    if (match.IsDonorKeyNull() || (match.DonorKey == 0))
                    {
                        string msg =
                            String.Format(Catalog.GetString("Cannot create a gift for transaction {0} since there is no valid donor."),
                                          transactionRow.Description);
                        AVerificationResult.Add(new TVerificationResult(Catalog.GetString("Creating Gift Batch"), msg, TResultSeverity.Resv_Critical));
                        DBAccess.GDBAccessObj.RollbackTransaction();
                        return(-1);
                    }
                }
            }

            string MatchedGiftReference = stmt.Filename;

            if (!stmt.IsBankAccountKeyNull())
            {
                string sqlGetBankSortCode =
                    "SELECT bank.p_branch_code_c " +
                    "FROM PUB_p_banking_details details, PUB_p_bank bank " +
                    "WHERE details.p_banking_details_key_i = ?" +
                    "AND details.p_bank_key_n = bank.p_partner_key_n";
                OdbcParameter param = new OdbcParameter("detailkey", OdbcType.Int);
                param.Value = stmt.BankAccountKey;

                PBankTable bankTable = new PBankTable();
                DBAccess.GDBAccessObj.SelectDT(bankTable, sqlGetBankSortCode, Transaction, new OdbcParameter[] { param }, 0, 0);

                MatchedGiftReference = bankTable[0].BranchCode + " " + stmt.Date.Day.ToString();
            }

            DBAccess.GDBAccessObj.RollbackTransaction();

            GiftBatchTDS GiftDS = TGiftTransactionWebConnector.CreateAGiftBatch(
                ALedgerNumber,
                BatchDateEffective,
                String.Format(Catalog.GetString("bank import for date {0}"), stmt.Date.ToShortDateString()));

            AGiftBatchRow giftbatchRow = GiftDS.AGiftBatch[0];

            giftbatchRow.BankAccountCode = stmt.BankAccountCode;

            decimal HashTotal = 0.0M;

            MainDS.AEpTransaction.DefaultView.Sort =
                AEpTransactionTable.GetNumberOnPaperStatementDBName();

            MainDS.AEpMatch.DefaultView.RowFilter = String.Empty;
            MainDS.AEpMatch.DefaultView.Sort      =
                AEpMatchTable.GetActionDBName() + ", " +
                AEpMatchTable.GetMatchTextDBName();

            int counter = 5;

            foreach (DataRowView dv in MainDS.AEpTransaction.DefaultView)
            {
                TProgressTracker.SetCurrentState(MyClientID,
                                                 Catalog.GetString("Preparing the gifts"),
                                                 counter++);

                AEpTransactionRow transactionRow = (AEpTransactionRow)dv.Row;

                DataRowView[] matches = MainDS.AEpMatch.DefaultView.FindRows(new object[] {
                    MFinanceConstants.BANK_STMT_STATUS_MATCHED_GIFT,
                    transactionRow.MatchText
                });

                if (matches.Length > 0)
                {
                    AEpMatchRow match = (AEpMatchRow)matches[0].Row;

                    AGiftRow gift = GiftDS.AGift.NewRowTyped();
                    gift.LedgerNumber          = giftbatchRow.LedgerNumber;
                    gift.BatchNumber           = giftbatchRow.BatchNumber;
                    gift.GiftTransactionNumber = giftbatchRow.LastGiftNumber + 1;
                    gift.DonorKey    = match.DonorKey;
                    gift.DateEntered = transactionRow.DateEffective;
                    gift.Reference   = MatchedGiftReference;
                    GiftDS.AGift.Rows.Add(gift);
                    giftbatchRow.LastGiftNumber++;

                    foreach (DataRowView r in matches)
                    {
                        match = (AEpMatchRow)r.Row;

                        AGiftDetailRow detail = GiftDS.AGiftDetail.NewRowTyped();
                        detail.LedgerNumber          = gift.LedgerNumber;
                        detail.BatchNumber           = gift.BatchNumber;
                        detail.GiftTransactionNumber = gift.GiftTransactionNumber;
                        detail.DetailNumber          = gift.LastDetailNumber + 1;
                        gift.LastDetailNumber++;

                        detail.GiftTransactionAmount = match.GiftTransactionAmount;
                        detail.GiftAmount            = match.GiftTransactionAmount;
                        HashTotal += match.GiftTransactionAmount;
                        detail.MotivationGroupCode  = match.MotivationGroupCode;
                        detail.MotivationDetailCode = match.MotivationDetailCode;

                        // do not use the description in comment one, because that could show up on the gift receipt???
                        // detail.GiftCommentOne = transactionRow.Description;

                        detail.CommentOneType        = MFinanceConstants.GIFT_COMMENT_TYPE_BOTH;
                        detail.CostCentreCode        = match.CostCentreCode;
                        detail.RecipientKey          = match.RecipientKey;
                        detail.RecipientLedgerNumber = match.RecipientLedgerNumber;

                        AMotivationDetailRow motivation = (AMotivationDetailRow)MainDS.AMotivationDetail.Rows.Find(
                            new object[] { ALedgerNumber, detail.MotivationGroupCode, detail.MotivationDetailCode });

                        if (motivation == null)
                        {
                            AVerificationResult.Add(new TVerificationResult(
                                                        String.Format(Catalog.GetString("creating gift for match {0}"), transactionRow.Description),
                                                        String.Format(Catalog.GetString("Cannot find motivation group '{0}' and motivation detail '{1}'"),
                                                                      detail.MotivationGroupCode, detail.MotivationDetailCode),
                                                        TResultSeverity.Resv_Critical));
                        }

                        if (detail.CostCentreCode.Length == 0)
                        {
                            // try to retrieve the current costcentre for this recipient
                            if (detail.RecipientKey != 0)
                            {
                                detail.RecipientLedgerNumber = TGiftTransactionWebConnector.GetRecipientFundNumber(detail.RecipientKey);

                                detail.CostCentreCode = TGiftTransactionWebConnector.IdentifyPartnerCostCentre(detail.LedgerNumber,
                                                                                                               detail.RecipientLedgerNumber);
                            }
                            else
                            {
                                if (motivation != null)
                                {
                                    detail.CostCentreCode = motivation.CostCentreCode;
                                }
                            }
                        }

                        // check for active cost centre
                        ACostCentreRow costcentre = (ACostCentreRow)MainDS.ACostCentre.Rows.Find(new object[] { ALedgerNumber, detail.CostCentreCode });

                        if ((costcentre == null) || !costcentre.CostCentreActiveFlag)
                        {
                            AVerificationResult.Add(new TVerificationResult(
                                                        String.Format(Catalog.GetString("creating gift for match {0}"), transactionRow.Description),
                                                        Catalog.GetString("Invalid or inactive cost centre"),
                                                        TResultSeverity.Resv_Critical));
                        }

                        GiftDS.AGiftDetail.Rows.Add(detail);
                    }
                }
            }

            TProgressTracker.SetCurrentState(MyClientID,
                                             Catalog.GetString("Submit to database"),
                                             counter++);

            if (AVerificationResult.HasCriticalErrors)
            {
                return(-1);
            }

            giftbatchRow.HashTotal  = HashTotal;
            giftbatchRow.BatchTotal = HashTotal;

            // do not overwrite the parameter, because there might be the hint for a different gift batch date
            TVerificationResultCollection VerificationResultSubmitChanges;

            TSubmitChangesResult result = TGiftTransactionWebConnector.SaveGiftBatchTDS(ref GiftDS,
                                                                                        out VerificationResultSubmitChanges);

            TProgressTracker.FinishJob(MyClientID);

            if (result == TSubmitChangesResult.scrOK)
            {
                return(giftbatchRow.BatchNumber);
            }

            return(-1);
        }
        /// <summary>
        /// dump unmatched gifts or other transactions to a HTML table for printing
        /// </summary>
        private static string PrintHTML(
            AEpStatementRow ACurrentStatement,
            DataView AEpTransactions, AEpMatchTable AMatches, string ATitle,
            string ALetterTemplateFilename)
        {
            if ((ALetterTemplateFilename.Length == 0) || !File.Exists(ALetterTemplateFilename))
            {
                OpenFileDialog DialogOpen = new OpenFileDialog();
                DialogOpen.Filter = "Report template (*.html)|*.html";
                DialogOpen.RestoreDirectory = true;
                DialogOpen.Title = "Open Report Template";

                if (DialogOpen.ShowDialog() == DialogResult.OK)
                {
                    ALetterTemplateFilename = DialogOpen.FileName;
                }
            }

            // message body from HTML template
            StreamReader reader = new StreamReader(ALetterTemplateFilename);
            string msg = reader.ReadToEnd();

            reader.Close();

            msg = msg.Replace("#TITLE", ATitle);
            msg = msg.Replace("#PRINTDATE", DateTime.Now.ToShortDateString());

            if (!ACurrentStatement.IsIdFromBankNull())
            {
                msg = msg.Replace("#STATEMENTNR", ACurrentStatement.IdFromBank);
            }

            if (!ACurrentStatement.IsStartBalanceNull())
            {
                msg = msg.Replace("#STARTBALANCE", String.Format("{0:N}", ACurrentStatement.StartBalance));
            }

            if (!ACurrentStatement.IsEndBalanceNull())
            {
                msg = msg.Replace("#ENDBALANCE", String.Format("{0:N}", ACurrentStatement.EndBalance));
            }

            // recognise detail lines automatically
            string RowTemplate;
            msg = TPrinterHtml.GetTableRow(msg, "#NRONSTATEMENT", out RowTemplate);
            string rowTexts = "";

            BankImportTDSAEpTransactionRow row = null;

            AEpTransactions.Sort = BankImportTDSAEpTransactionTable.GetNumberOnPaperStatementDBName();

            Decimal Sum = 0.0m;
            Int32 NumberPrinted = 0;

            DataView MatchesByMatchText = new DataView(AMatches,
                string.Empty,
                AEpMatchTable.GetMatchTextDBName(),
                DataViewRowState.CurrentRows);

            string thinLine = "<font size=\"-3\">-------------------------------------------------------------------------<br/></font>";

            foreach (DataRowView rv in AEpTransactions)
            {
                row = (BankImportTDSAEpTransactionRow)rv.Row;

                string rowToPrint = RowTemplate;

                // short description, remove all SEPA stuff
                string ShortDescription = RemoveSEPAText(row.Description);

                rowToPrint = rowToPrint.Replace("#NAME", row.AccountName);
                rowToPrint = rowToPrint.Replace("#DESCRIPTION", row.Description);
                rowToPrint = rowToPrint.Replace("#SHORTDESCRIPTION", ShortDescription);

                string RecipientDescription = string.Empty;

                DataRowView[] matches = MatchesByMatchText.FindRows(row.MatchText);

                AEpMatchRow match = null;

                foreach (DataRowView rvMatch in matches)
                {
                    match = (AEpMatchRow)rvMatch.Row;

                    if (RecipientDescription.Length > 0)
                    {
                        RecipientDescription += "<br/>";
                    }

                    if (!match.IsRecipientKeyNull() && (match.RecipientKey > 0))
                    {
                        RecipientDescription += match.RecipientKey.ToString() + " ";
                    }

                    RecipientDescription += match.RecipientShortName;
                }

                if (RecipientDescription.Trim().Length > 0)
                {
                    rowToPrint = rowToPrint.Replace("#RECIPIENTDESCRIPTIONUNMATCHED", string.Empty);
                    rowToPrint = rowToPrint.Replace("#RECIPIENTDESCRIPTION", "<br/>" + thinLine + RecipientDescription);
                }
                else
                {
                    // extra space for unmatched gifts
                    rowToPrint = rowToPrint.Replace("#RECIPIENTDESCRIPTIONUNMATCHED", "<br/><br/>");
                    rowToPrint = rowToPrint.Replace("#RECIPIENTDESCRIPTION", string.Empty);
                }

                if ((match != null) && !match.IsDonorKeyNull() && (match.DonorKey > 0))
                {
                    string DonorDescription = "<br/>" + thinLine + match.DonorKey.ToString() + " " + match.DonorShortName;

                    rowToPrint = rowToPrint.Replace("#DONORDESCRIPTION", DonorDescription);
                    rowToPrint = rowToPrint.Replace("#DONORKEY", StringHelper.PartnerKeyToStr(match.DonorKey));
                    rowToPrint = rowToPrint.Replace("#DONORNAMEORDESCRIPTION", match.DonorShortName);
                }
                else
                {
                    rowToPrint = rowToPrint.Replace("#DONORDESCRIPTION", string.Empty);
                    rowToPrint = rowToPrint.Replace("#DONORKEY", string.Empty);
                    rowToPrint = rowToPrint.Replace("#DONORNAMEORDESCRIPTION", row.AccountName);
                }

                rowTexts += rowToPrint.
                            Replace("#NRONSTATEMENT", row.NumberOnPaperStatement.ToString()).
                            Replace("#AMOUNT", String.Format("{0:C}", row.TransactionAmount)).
                            Replace("#IBANANDBIC",
                    row.IsIbanNull() ? string.Empty : "<br/>" + row.Iban + "<br/>" + row.Bic).
                            Replace("#IBAN", row.Iban).
                            Replace("#BIC", row.Bic).
                            Replace("#ACCOUNTNUMBER", row.BankAccountNumber).
                            Replace("#BANKSORTCODE", row.BranchCode);

                Sum += Convert.ToDecimal(row.TransactionAmount);
                NumberPrinted++;
            }

            Sum = Math.Round(Sum, 2);

            msg = msg.Replace("#ROWTEMPLATE", rowTexts);
            msg = msg.Replace("#TOTALAMOUNT", String.Format("{0:C}", Sum));
            msg = msg.Replace("#TOTALNUMBER", NumberPrinted.ToString());

            return msg;
        }
        /// <summary>
        /// select the bank statement that should be loaded
        /// </summary>
        /// <param name="AStatementKey"></param>
        private void SelectBankStatement(Int32 AStatementKey)
        {
            CurrentlySelectedMatch = null;
            CurrentStatement = null;

            // merge the cost centres and the motivation details from the cacheable tables
            FMainDS.ACostCentre.Merge(TDataCache.TMFinance.GetCacheableFinanceTable(TCacheableFinanceTablesEnum.CostCentreList, FLedgerNumber));
            FMainDS.AMotivationDetail.Merge(TDataCache.TMFinance.GetCacheableFinanceTable(TCacheableFinanceTablesEnum.MotivationList, FLedgerNumber));
            FMainDS.ACostCentre.AcceptChanges();
            FMainDS.AMotivationDetail.AcceptChanges();

            // load the transactions of the selected statement, and the matches
            Thread t = new Thread(() => GetBankStatementTransactionsAndMatches(AStatementKey));

            using (TProgressDialog dialog = new TProgressDialog(t))
            {
                if (dialog.ShowDialog() == DialogResult.Cancel)
                {
                    return;
                }
            }

            while (FMainDS.AEpStatement.Rows.Count != 1)
            {
                // wait for the merging of the dataset to finish in the thread
                Thread.Sleep(300);
            }

            // an old version of the CSV import plugin did not set the potential gift typecode
            foreach (AEpTransactionRow r in FMainDS.AEpTransaction.Rows)
            {
                if (r.IsTransactionTypeCodeNull() && (r.TransactionAmount > 0))
                {
                    r.TransactionTypeCode = MFinanceConstants.BANK_STMT_POTENTIAL_GIFT;
                }
            }

            CurrentStatement = (AEpStatementRow)FMainDS.AEpStatement[0];

            FTransactionView = FMainDS.AEpTransaction.DefaultView;
            FTransactionView.AllowNew = false;
            FTransactionView.Sort = AEpTransactionTable.GetOrderDBName() + " ASC";
            grdAllTransactions.DataSource = new DevAge.ComponentModel.BoundDataView(FTransactionView);

            TFinanceControls.InitialiseMotivationGroupList(ref cmbMotivationGroup, FLedgerNumber, true);
            TFinanceControls.InitialiseMotivationDetailList(ref cmbMotivationDetail, FLedgerNumber, true);
            TFinanceControls.InitialiseCostCentreList(ref cmbGLCostCentre, FLedgerNumber, true, false, true, true);
            TFinanceControls.InitialiseAccountList(ref cmbGLAccount, FLedgerNumber, true, false, true, false);

            FMatchView = FMainDS.AEpMatch.DefaultView;
            FMatchView.AllowNew = false;
            grdGiftDetails.DataSource = new DevAge.ComponentModel.BoundDataView(FMatchView);

            TFinanceControls.InitialiseAccountList(ref cmbBankAccount, FLedgerNumber, true, false, true, true);

            if (CurrentStatement != null)
            {
                FMainDS.AEpStatement.DefaultView.RowFilter = String.Format("{0}={1}",
                    AEpStatementTable.GetStatementKeyDBName(),
                    CurrentStatement.StatementKey);
                cmbBankAccount.SetSelectedString(CurrentStatement.BankAccountCode);
                txtBankStatement.Text = CurrentStatement.Filename;
                dtpBankStatementDate.Date = CurrentStatement.Date;
                FMainDS.AEpStatement.DefaultView.RowFilter = string.Empty;
            }

            TransactionFilterChanged(null, null);
            grdAllTransactions.SelectRowInGrid(1);
            grdAllTransactions.AutoResizeGrid();
        }
コード例 #10
0
        /// <summary>
        /// this can be used from the unit tests
        /// </summary>
        public static BankImportTDS ImportBankStatementHelper(Int32 ALedgerNumber,
                                                              string ABankAccountCode,
                                                              string ASeparator,
                                                              string ADateFormat,
                                                              string ANumberFormat,
                                                              string ACurrencyCode,
                                                              string AColumnsUsage,
                                                              string AStartAfterLine,
                                                              string ABankStatementFilename,
                                                              string AStatementData)
        {
            Int32  FirstTransactionRow = 0;
            string DateFormat          = (ADateFormat == "MDY" ? "M/d/yyyy" : "d.M.yyyy");
            string ThousandsSeparator  = (ANumberFormat == "American" ? "," : ".");
            string DecimalSeparator    = (ANumberFormat == "American" ? "." : ",");

            List <String> StatementData = new List <string>();

            string [] stmtarray = AStatementData.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string line in stmtarray)
            {
                StatementData.Add(line);
            }

            // skip headers
            Int32 lineCounter = FirstTransactionRow;

            // TODO: support splitting a file by month?
            // at the moment this only works for files that are already split by month
            // TODO: check if this statement has already been imported, by the stmt.Filename; delete old statement
            BankImportTDS   MainDS = new BankImportTDS();
            AEpStatementRow stmt   = MainDS.AEpStatement.NewRowTyped();

            stmt.StatementKey = -1;

            // TODO: BankAccountKey should be NOT NULL. for the moment not time to implement
            // stmt.BankAccountKey = Convert.ToInt64(TXMLParser.GetAttribute(RootNode, "BankAccountKey"));
            stmt.Filename = Path.GetFileName(ABankStatementFilename.Replace('\\', Path.DirectorySeparatorChar));

            // depending on the path of BankStatementFilename you could determine between several bank accounts
            // search all config parameters starting with "BankNameFor",
            // and see if the rest of the parameter name is part of the filename or path
            StringCollection BankNameForParameters = TAppSettingsManager.GetKeys("BankNameFor");

            foreach (string BankNameForParameter in BankNameForParameters)
            {
                if (stmt.Filename.ToLower().Contains(BankNameForParameter.Substring("BankNameFor".Length).ToLower()))
                {
                    stmt.Filename = TAppSettingsManager.GetValue(BankNameForParameter);
                }
            }

            if (stmt.Filename.Length > AEpStatementTable.GetFilenameLength())
            {
                // use the last number of characters of the path and filename
                stmt.Filename = ABankStatementFilename.Substring(ABankStatementFilename.Length - AEpStatementTable.GetFilenameLength());
            }

            stmt.LedgerNumber    = ALedgerNumber;
            stmt.CurrencyCode    = ACurrencyCode;
            stmt.BankAccountCode = ABankAccountCode;
            MainDS.AEpStatement.Rows.Add(stmt);

            // TODO would need to allow the user to change the order&meaning of columns
            string[] ColumnsUsage = AColumnsUsage.Split(new char[] { ',' });
            Dictionary <DateTime, List <AEpTransactionRow> > TransactionsPerMonth = new Dictionary <DateTime, List <AEpTransactionRow> >();

            bool startParsing = (AStartAfterLine == String.Empty);

            for (; lineCounter < StatementData.Count; lineCounter++)
            {
                string line = StatementData[lineCounter];

                if (AStartAfterLine == line)
                {
                    startParsing = true;
                    continue;
                }

                if (!startParsing)
                {
                    continue;
                }

                AEpTransactionRow row = MainDS.AEpTransaction.NewRowTyped();
                row.StatementKey = stmt.StatementKey;

                foreach (string UseAs in ColumnsUsage)
                {
                    if (line == String.Empty)
                    {
                        // this line is too short, does not have enough columns.
                        // ignore this row.
                        row = null;
                        continue;
                    }

                    string Value = StringHelper.GetNextCSV(ref line, StatementData, ref lineCounter, ASeparator);

                    if (UseAs.ToLower() == "dateeffective")
                    {
                        if (Value.Length == "dd.mm.yy".Length)
                        {
                            DateFormat = DateFormat.Replace("yyyy", "yy");
                        }

                        try
                        {
                            row.DateEffective = XmlConvert.ToDateTime(Value, DateFormat);
                        }
                        catch (Exception)
                        {
                            TLogging.Log("Problem with date effective: " + Value + " (Format: " + DateFormat + ")");
                        }
                    }
                    else if (UseAs.ToLower() == "accountname")
                    {
                        if (row.AccountName.Length > 0)
                        {
                            row.AccountName += " ";
                        }

                        row.AccountName += Value;
                    }
                    else if (UseAs.ToLower() == "description")
                    {
                        // remove everything after DTA; it is not relevant and confused matching
                        if (Value.IndexOf(" DTA ") > 0)
                        {
                            Value = Value.Substring(0, Value.IndexOf(" DTA "));
                        }

                        if (row.Description.Length > 0)
                        {
                            row.Description += " ";
                        }

                        row.Description += Value;
                    }
                    else if (UseAs.ToLower() == "amount")
                    {
                        if (Value.Contains(" "))
                        {
                            // cut off currency code; should have been defined in the data description file, for the whole batch
                            Value = Value.Substring(0, Value.IndexOf(" ") - 1);
                        }

                        Value = Value.Replace(ThousandsSeparator, "");
                        Value = Value.Replace(DecimalSeparator, ".");

                        row.TransactionAmount = Convert.ToDecimal(Value, System.Globalization.CultureInfo.InvariantCulture);
                    }
                    else if (UseAs.ToLower() == "directdebiths")
                    {
                        if (Value == "S")
                        {
                            row.TransactionAmount *= -1;
                        }
                    }
                    else if (UseAs.ToLower() == "currency")
                    {
                        if (stmt.CurrencyCode == string.Empty)
                        {
                            stmt.CurrencyCode = Value.ToUpper();
                        }
                        else if (stmt.CurrencyCode != Value.ToUpper())
                        {
                            throw new Exception("cannot mix several currencies in the same bank statement file");
                        }
                    }
                }

                if (row == null)
                {
                    // ignore this line
                    continue;
                }

                // all transactions with positive amount can be donations
                if (row.TransactionAmount > 0)
                {
                    row.TransactionTypeCode = MFinanceConstants.BANK_STMT_POTENTIAL_GIFT;
                }

                DateTime month = new DateTime(row.DateEffective.Year, row.DateEffective.Month, 1);
                if (!TransactionsPerMonth.ContainsKey(month))
                {
                    TransactionsPerMonth.Add(month, new List <AEpTransactionRow>());
                }
                TransactionsPerMonth[month].Add(row);
            }

            if (TransactionsPerMonth.Keys.Count == 0)
            {
                // cannot find any transactions
                return(MainDS);
            }

            // now find the month that should be imported
            DateTime MonthToBeImported = DateTime.MinValue;

            foreach (DateTime month in TransactionsPerMonth.Keys)
            {
                if (MonthToBeImported == DateTime.MinValue)
                {
                    MonthToBeImported = month;
                }
                else
                {
                    if (TransactionsPerMonth[month].Count > TransactionsPerMonth[MonthToBeImported].Count)
                    {
                        MonthToBeImported = month;
                    }
                }
            }

            DateTime latestDate = DateTime.MinValue;
            Int32    rowCount   = 0;

            foreach (AEpTransactionRow row in TransactionsPerMonth[MonthToBeImported])
            {
                rowCount++;

                row.Order = rowCount;
                row.NumberOnPaperStatement = row.Order;

                MainDS.AEpTransaction.Rows.Add(row);
                if (row.DateEffective > latestDate)
                {
                    latestDate = row.DateEffective;
                }
            }

            stmt.Date = latestDate;

            return(MainDS);
        }
コード例 #11
0
        /// <summary>
        /// import one MT940 file, split into multiple statements per year
        /// </summary>
        static public bool ImportFromFile(
            Int32 ALedgerNumber,
            string ABankAccountCode,
            string AFileName,
            string AFileContent,
            bool AParsePreviousYear,
            out Int32 AStatementKey,
            out TVerificationResultCollection AVerificationResult)
        {
            AVerificationResult = new TVerificationResultCollection();
            TSwiftParser parser = new TSwiftParser();

            parser.ProcessFileContent(AFileContent);

            BankImportTDS MainDS           = new BankImportTDS();
            Int32         statementCounter = MainDS.AEpStatement.Rows.Count;

            foreach (TStatement stmt in parser.statements)
            {
                Int32 transactionCounter = 0;

                foreach (TTransaction tr in stmt.transactions)
                {
                    BankImportTDSAEpTransactionRow row = MainDS.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: http://www.hettwer-beratung.de/sepa-spezialwissen/sepa-technische-anforderungen/sepa-gesch%C3%A4ftsvorfallcodes-gvc-mt-940/
                    if ((row.TransactionTypeCode == "052") ||
                        (row.TransactionTypeCode == "051") ||
                        (row.TransactionTypeCode == "053") ||
                        (row.TransactionTypeCode == "067") ||
                        (row.TransactionTypeCode == "068") ||
                        (row.TransactionTypeCode == "069") ||
                        (row.TransactionTypeCode == "119") || /* Einzelbuchung Spende (Purpose: CHAR) */
                        (row.TransactionTypeCode == "152") || /* SEPA Credit Transfer Einzelbuchung Dauerauftrag */
                        (row.TransactionTypeCode == "166") || /* SEPA Credit Transfer */
                        (row.TransactionTypeCode == "169")    /* SEPA Credit Transfer Donation */
                        )
                    {
                        row.TransactionTypeCode += MFinanceConstants.BANK_STMT_POTENTIAL_GIFT;
                    }

                    MainDS.AEpTransaction.Rows.Add(row);

                    transactionCounter++;
                }

                AEpStatementRow epstmt = MainDS.AEpStatement.NewRowTyped();
                epstmt.StatementKey    = (statementCounter + 1) * -1;
                epstmt.LedgerNumber    = ALedgerNumber;
                epstmt.Date            = stmt.date;
                epstmt.CurrencyCode    = stmt.currency;
                epstmt.Filename        = AFileName;
                epstmt.BankAccountCode = ABankAccountCode;
                epstmt.IdFromBank      = stmt.id;

                if (AFileName.Length > AEpStatementTable.GetFilenameLength())
                {
                    epstmt.Filename =
                        TAppSettingsManager.GetValue("BankNameFor" + stmt.bankCode + "/" + stmt.accountCode,
                                                     stmt.bankCode + "/" + stmt.accountCode, true);
                }

                epstmt.StartBalance = stmt.startBalance;
                epstmt.EndBalance   = stmt.endBalance;

                MainDS.AEpStatement.Rows.Add(epstmt);

                // sort by amount, and by accountname; this is the order of the paper statements and attachments
                MainDS.AEpTransaction.DefaultView.Sort = BankImportTDSAEpTransactionTable.GetTransactionAmountDBName() + "," +
                                                         BankImportTDSAEpTransactionTable.GetOrderDBName();
                MainDS.AEpTransaction.DefaultView.RowFilter = BankImportTDSAEpTransactionTable.GetStatementKeyDBName() + "=" +
                                                              epstmt.StatementKey.ToString();

                // starting with the most negative amount, which should be the last in the order on the statement
                Int32 countOrderOnStatement = MainDS.AEpTransaction.DefaultView.Count;
                bool  countingNegative      = true;

                foreach (DataRowView rv in MainDS.AEpTransaction.DefaultView)
                {
                    BankImportTDSAEpTransactionRow row = (BankImportTDSAEpTransactionRow)rv.Row;

                    if ((row.TransactionAmount > 0) && countingNegative)
                    {
                        countingNegative      = false;
                        countOrderOnStatement = 1;
                    }

                    if (countingNegative)
                    {
                        row.NumberOnPaperStatement = countOrderOnStatement;
                        countOrderOnStatement--;
                    }
                    else
                    {
                        row.NumberOnPaperStatement = countOrderOnStatement;
                        countOrderOnStatement++;
                    }
                }

                statementCounter++;
            }

            if (TBankStatementImport.StoreNewBankStatement(
                    MainDS,
                    out AStatementKey) == TSubmitChangesResult.scrOK)
            {
                return(true);
            }

            return(false);
        }
コード例 #12
0
        /// <summary>
        /// import one CAMT file, split into multiple statements per year
        /// </summary>
        static public bool ImportFromFile(
            Int32 ALedgerNumber,
            string ABankAccountCode,
            string AFileName,
            string AFileContent,
            bool AParsePreviousYear,
            out Int32 AStatementKey,
            out TVerificationResultCollection AVerificationResult)
        {
            TCAMTParser parser = new TCAMTParser();

            AStatementKey = -1;

            parser.ProcessFileContent(AFileContent, AParsePreviousYear, out AVerificationResult);

            if (AVerificationResult.HasCriticalErrors)
            {
                return(false);
            }

            BankImportTDS MainDS           = new BankImportTDS();
            Int32         statementCounter = MainDS.AEpStatement.Rows.Count;

            foreach (TStatement stmt in parser.statements)
            {
                if (stmt.severalYears && !AParsePreviousYear)
                {
                    // parse the transactions of the previous year separately
                    ImportFromFile(ALedgerNumber, ABankAccountCode, AFileName, AFileContent,
                                   true,
                                   out AStatementKey, out AVerificationResult);

                    if (AVerificationResult.HasCriticalErrors)
                    {
                        return(false);
                    }
                }

                Int32 transactionCounter = 0;

                foreach (TTransaction tr in stmt.transactions)
                {
                    BankImportTDSAEpTransactionRow row = MainDS.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") ||
                        (row.TransactionTypeCode == "067") ||
                        (row.TransactionTypeCode == "068") ||
                        (row.TransactionTypeCode == "069") ||
                        (row.TransactionTypeCode == "119") || /* Einzelbuchung Spende (Purpose: CHAR) */
                        (row.TransactionTypeCode == "152") || /* SEPA Credit Transfer Einzelbuchung Dauerauftrag */
                        (row.TransactionTypeCode == "166") || /* SEPA Credit Transfer */
                        (row.TransactionTypeCode == "169")    /* SEPA Credit Transfer Donation */
                        )
                    {
                        // only incoming money is a potential gift
                        if (row.TransactionAmount > 0)
                        {
                            row.TransactionTypeCode += MFinanceConstants.BANK_STMT_POTENTIAL_GIFT;
                        }
                    }

                    MainDS.AEpTransaction.Rows.Add(row);

                    transactionCounter++;
                }

                AEpStatementRow epstmt = MainDS.AEpStatement.NewRowTyped();
                epstmt.LedgerNumber    = ALedgerNumber;
                epstmt.StatementKey    = (statementCounter + 1) * -1;
                epstmt.Date            = stmt.date;
                epstmt.CurrencyCode    = stmt.currency;
                epstmt.BankAccountCode = ABankAccountCode;
                epstmt.IdFromBank      = stmt.id;

                if (AFileName.Length > AEpStatementTable.GetFilenameLength())
                {
                    epstmt.Filename =
                        stmt.bankCode + "/" + stmt.accountCode;
                }
                else
                {
                    epstmt.Filename = AFileName;
                }

                epstmt.StartBalance = stmt.startBalance;
                epstmt.EndBalance   = stmt.endBalance;

                MainDS.AEpStatement.Rows.Add(epstmt);

                // sort by amount, and by accountname; this is the order of the paper statements and attachments
                MainDS.AEpTransaction.DefaultView.Sort = BankImportTDSAEpTransactionTable.GetTransactionAmountDBName() + "," +
                                                         BankImportTDSAEpTransactionTable.GetOrderDBName();
                MainDS.AEpTransaction.DefaultView.RowFilter = BankImportTDSAEpTransactionTable.GetStatementKeyDBName() + "=" +
                                                              epstmt.StatementKey.ToString();

                // starting with the most negative amount, which should be the last in the order on the statement
                Int32 countOrderOnStatement = MainDS.AEpTransaction.DefaultView.Count;
                bool  countingNegative      = true;

                foreach (DataRowView rv in MainDS.AEpTransaction.DefaultView)
                {
                    BankImportTDSAEpTransactionRow row = (BankImportTDSAEpTransactionRow)rv.Row;

                    if ((row.TransactionAmount > 0) && countingNegative)
                    {
                        countingNegative      = false;
                        countOrderOnStatement = 1;
                    }

                    if (countingNegative)
                    {
                        row.NumberOnPaperStatement = countOrderOnStatement;
                        countOrderOnStatement--;
                    }
                    else
                    {
                        row.NumberOnPaperStatement = countOrderOnStatement;
                        countOrderOnStatement++;
                    }
                }

                statementCounter++;
            }

            if (TBankStatementImport.StoreNewBankStatement(
                    MainDS,
                    out AStatementKey) == TSubmitChangesResult.scrOK)
            {
                return(true);
            }

            return(false);
        }
コード例 #13
0
        /// <summary>
        /// there are several gift batches that might fit this bank statement. find the right one!
        /// simple matching; no split gifts, bank account number fits and amount fits
        /// </summary>
        private static int FindGiftBatch(BankImportTDS AMainDS, AEpStatementRow AStmt)
        {
            SortedList <Int32, Int32>MatchedGiftBatches = new SortedList <int, int>();

            // create the dataview only after loading, otherwise loading is much slower
            DataView GiftDetailByAmountAndDonor = new DataView(AMainDS.AGiftDetail,
                string.Empty,
                AGiftDetailTable.GetGiftAmountDBName() + "," +
                BankImportTDSAGiftDetailTable.GetDonorKeyDBName(),
                DataViewRowState.CurrentRows);

            DataView GiftByAmountAndDonor = new DataView(AMainDS.AGift,
                string.Empty,
                BankImportTDSAGiftTable.GetTotalAmountDBName() + "," +
                AGiftTable.GetDonorKeyDBName(),
                DataViewRowState.CurrentRows);

            AMainDS.PBankingDetails.DefaultView.Sort = BankImportTDSPBankingDetailsTable.GetBankSortCodeDBName() + "," +
                                                       BankImportTDSPBankingDetailsTable.GetBankAccountNumberDBName();

            foreach (BankImportTDSAEpTransactionRow transaction in AMainDS.AEpTransaction.Rows)
            {
                // find the donor for this transaction, by his bank account number
                Int64 DonorKey = GetDonorByBankAccountNumber(AMainDS, transaction.BranchCode, transaction.BankAccountNumber);

                if (transaction.BankAccountNumber.Length == 0)
                {
                    // useful for NUnit testing for csv import: partnerkey in description
                    try
                    {
                        DonorKey = Convert.ToInt64(transaction.Description);
                    }
                    catch (Exception)
                    {
                        DonorKey = -1;
                    }
                }

                BankImportTDSAGiftDetailRow detailrow = null;

                if (DonorKey != -1)
                {
                    DataRowView[] giftDetails = GiftDetailByAmountAndDonor.FindRows(new object[] { transaction.TransactionAmount, DonorKey });

                    if (giftDetails.Length == 1)
                    {
                        // found a possible match
                        detailrow = (BankImportTDSAGiftDetailRow)giftDetails[0].Row;
                    }
                    else
                    {
                        // check if we can find a gift with several gift details, that would match this transaction amount
                        DataRowView[] gifts = GiftByAmountAndDonor.FindRows(new object[] { transaction.TransactionAmount, DonorKey });

                        if (gifts.Length >= 1)
                        {
                            AGiftRow gift = (AGiftRow)gifts[0].Row;
                            detailrow =
                                (BankImportTDSAGiftDetailRow)AMainDS.AGiftDetail.Rows.Find(new object[] { gift.LedgerNumber, gift.BatchNumber,
                                                                                                          gift.GiftTransactionNumber,
                                                                                                          1 });
                        }
                    }
                }

                if (detailrow != null)
                {
                    if (MatchedGiftBatches.ContainsKey(detailrow.BatchNumber))
                    {
                        MatchedGiftBatches[detailrow.BatchNumber]++;
                    }
                    else
                    {
                        MatchedGiftBatches.Add(detailrow.BatchNumber, 1);
                    }
                }
            }

            int SelectedGiftBatch = -1;
            int maxMatches = 0;

            foreach (int GiftBatchNumber in MatchedGiftBatches.Keys)
            {
                if (MatchedGiftBatches[GiftBatchNumber] > maxMatches)
                {
                    maxMatches = MatchedGiftBatches[GiftBatchNumber];
                    SelectedGiftBatch = GiftBatchNumber;
                }
            }

            if ((SelectedGiftBatch != -1)
                && ((AMainDS.AEpTransaction.Rows.Count > 2)
                    && (MatchedGiftBatches[SelectedGiftBatch] < AMainDS.AEpTransaction.Rows.Count / 2)))
            {
                TLogging.Log(
                    "cannot find enough gifts that look the same, for statement " + AStmt.Filename +
                    ". CountMatches for batch " + SelectedGiftBatch.ToString() + ": " +
                    MatchedGiftBatches[SelectedGiftBatch].ToString());

                SelectedGiftBatch = -1;
            }

            return SelectedGiftBatch;
        }
コード例 #14
0
        private static void CreateMatches(BankImportTDS AMainDS,
            AEpStatementRow ACurrentStatement,
            Int32 ASelectedGiftBatch, bool APostedBatch)
        {
            // remove all gifts and giftdetails that don't belong to the selected batch
            List <DataRow>ToDelete = new List <DataRow>();

            foreach (AGiftDetailRow giftdetail in AMainDS.AGiftDetail.Rows)
            {
                if (giftdetail.BatchNumber != ASelectedGiftBatch)
                {
                    ToDelete.Add(giftdetail);
                }
            }

            foreach (DataRow del in ToDelete)
            {
                AMainDS.AGiftDetail.Rows.Remove(del);
            }

            ToDelete = new List <DataRow>();

            foreach (AGiftRow gift in AMainDS.AGift.Rows)
            {
                if (gift.BatchNumber != ASelectedGiftBatch)
                {
                    ToDelete.Add(gift);
                }
            }

            foreach (DataRow del in ToDelete)
            {
                AMainDS.AGift.Rows.Remove(del);
            }

            ToDelete = new List <DataRow>();

            foreach (BankImportTDSAEpTransactionRow transaction  in AMainDS.AEpTransaction.Rows)
            {
                // delete transactions with negative amount
                if (transaction.TransactionAmount < 0)
                {
                    ToDelete.Add(transaction);
                }
                else
                {
                    transaction.MatchAction = MFinanceConstants.BANK_STMT_STATUS_UNMATCHED;
                }
            }

            foreach (DataRow del in ToDelete)
            {
                AMainDS.AEpTransaction.Rows.Remove(del);
            }

            FindDonorKeysByBankAccount(AMainDS);

            AMainDS.PBankingDetails.DefaultView.Sort = BankImportTDSPBankingDetailsTable.GetPartnerKeyDBName();

            MatchDonorsWithKnownBankaccount(AMainDS);

            while (MatchTransactionsToGiftBatch(AMainDS))
            {
                ;
            }

            if (TLogging.DebugLevel > 0)
            {
                TLogging.Log("transactions not matched yet:");

                foreach (BankImportTDSAEpTransactionRow transaction in AMainDS.AEpTransaction.Rows)
                {
                    if (transaction.MatchAction != Ict.Petra.Shared.MFinance.MFinanceConstants.BANK_STMT_STATUS_MATCHED)
                    {
                        TLogging.Log(
                            "  " + transaction.DonorKey.ToString() + " " + transaction.AccountName + " --- " + transaction.Description + " " +
                            transaction.TransactionAmount.ToString());

                        if (transaction.DonorKey == -1)
                        {
                            TLogging.Log("     " + transaction.BankAccountNumber + " " + transaction.BranchCode);
                        }
                    }
                }

                TLogging.Log("gifts not matched yet:");

                foreach (BankImportTDSAGiftDetailRow giftdetail in AMainDS.AGiftDetail.Rows)
                {
                    if (!giftdetail.AlreadyMatched)
                    {
                        string HasBankDetails = "-";
                        int BankDetailsIndex = AMainDS.PBankingDetails.DefaultView.Find(giftdetail.DonorKey);

                        if (BankDetailsIndex != -1)
                        {
                            HasBankDetails = "*";
                        }

                        TLogging.Log(
                            "  " + HasBankDetails + " " + giftdetail.DonorKey.ToString() + " " + giftdetail.DonorShortName + " --- " +
                            giftdetail.RecipientDescription + " " + giftdetail.GiftAmount.ToString());

                        if (BankDetailsIndex != -1)
                        {
                            BankImportTDSPBankingDetailsRow bankdetail =
                                (BankImportTDSPBankingDetailsRow)AMainDS.PBankingDetails.DefaultView[BankDetailsIndex].Row;
                            TLogging.Log("     " + bankdetail.BankAccountNumber + " " + bankdetail.BankSortCode);
                        }
                    }
                }

                int CountMatched = 0;

                foreach (BankImportTDSAEpTransactionRow transaction in AMainDS.AEpTransaction.Rows)
                {
                    if (transaction.MatchAction == Ict.Petra.Shared.MFinance.MFinanceConstants.BANK_STMT_STATUS_MATCHED)
                    {
                        CountMatched++;
                    }
                }

                TLogging.Log("matched: " + CountMatched.ToString() + " of " + AMainDS.AEpTransaction.Rows.Count.ToString());
            }

            StoreCurrentMatches(AMainDS, ACurrentStatement.BankAccountCode);
        }