public static bool DropBankStatement(Int32 AEpStatementKey) { TDBTransaction Transaction = DBAccess.GDBAccessObj.BeginTransaction(IsolationLevel.ReadCommitted); BankImportTDS MainDS = new BankImportTDS(); AEpStatementAccess.LoadByPrimaryKey(MainDS, AEpStatementKey, Transaction); AEpTransactionAccess.LoadViaAEpStatement(MainDS, AEpStatementKey, Transaction); DBAccess.GDBAccessObj.RollbackTransaction(); foreach (AEpStatementRow stmtRow in MainDS.AEpStatement.Rows) { stmtRow.Delete(); } foreach (AEpTransactionRow transactionRow in MainDS.AEpTransaction.Rows) { transactionRow.Delete(); } MainDS.ThrowAwayAfterSubmitChanges = true; try { BankImportTDSAccess.SubmitChanges(MainDS); return(true); } catch (Exception) { return(false); } }
public static TSubmitChangesResult StoreNewBankStatement(BankImportTDS AStatementAndTransactionsDS, out Int32 AFirstStatementKey) { string MyClientID = DomainManager.GClientID.ToString(); AFirstStatementKey = -1; TProgressTracker.InitProgressTracker(MyClientID, Catalog.GetString("Processing new bank statements"), AStatementAndTransactionsDS.AEpStatement.Rows.Count + 1); TProgressTracker.SetCurrentState(MyClientID, Catalog.GetString("Saving to database"), 0); try { // Must not throw away the changes because we need the correct statement keys AStatementAndTransactionsDS.DontThrowAwayAfterSubmitChanges = true; BankImportTDSAccess.SubmitChanges(AStatementAndTransactionsDS); AFirstStatementKey = -1; if (AStatementAndTransactionsDS != null) { TProgressTracker.SetCurrentState(MyClientID, Catalog.GetString("starting to train"), 1); AFirstStatementKey = AStatementAndTransactionsDS.AEpStatement[0].StatementKey; // search for already posted gift batches, and do the matching for these imported statements TBankImportMatching.Train(AStatementAndTransactionsDS.AEpStatement); } TProgressTracker.FinishJob(MyClientID); } catch (Exception ex) { TLogging.Log(ex.ToString()); TProgressTracker.CancelJob(MyClientID); return(TSubmitChangesResult.scrError); } return(TSubmitChangesResult.scrOK); }
public static bool CommitMatches(BankImportTDS AMainDS) { if (AMainDS == null) { return(false); } AMainDS.ThrowAwayAfterSubmitChanges = true; try { BankImportTDSAccess.SubmitChanges(AMainDS); return(true); } catch (Exception) { return(false); } }
/// <summary> /// store historic Gift matches /// </summary> private static void StoreCurrentMatches(BankImportTDS AMatchDS, string ABankAccountCode) { TLogging.LogAtLevel(1, "StoreCurrentMatches..."); DataView GiftDetailView = new DataView( AMatchDS.AGiftDetail, string.Empty, BankImportTDSAGiftDetailTable.GetGiftTransactionNumberDBName() + "," + BankImportTDSAGiftDetailTable.GetDetailNumberDBName(), DataViewRowState.CurrentRows); SortedList <string, AEpMatchRow> MatchesToAddLater = new SortedList <string, AEpMatchRow>(); // for speed reasons, use a sortedlist instead of a dataview SortedList <string, AEpMatchRow> MatchesByText = new SortedList <string, AEpMatchRow>(); foreach (AEpMatchRow r in AMatchDS.AEpMatch.Rows) { MatchesByText[r.MatchText + ":::" + r.Detail.ToString()] = r; } foreach (BankImportTDSAEpTransactionRow tr in AMatchDS.AEpTransaction.Rows) { // create a match text which uniquely identifies this transaction string MatchText = CalculateMatchText(ABankAccountCode, tr); if (tr.MatchAction != MFinanceConstants.BANK_STMT_STATUS_MATCHED) { continue; } // get the gift details assigned to this transaction StringCollection GiftDetailNumbers = StringHelper.GetCSVList(tr.GiftDetailNumbers, ",", false); foreach (string strDetailNumber in GiftDetailNumbers) { DataRowView[] FilteredGiftDetails = GiftDetailView.FindRows( new object[] { tr.GiftTransactionNumber, Convert.ToInt32(strDetailNumber) }); // add new matches, and modify existing matches UpdateMatches( AMatchDS, (BankImportTDSAGiftDetailRow)FilteredGiftDetails[0].Row, MatchText, Convert.ToInt32(strDetailNumber) - 1, MatchesByText, MatchesToAddLater); } } // for speed reasons, add the new rows at the end foreach (AEpMatchRow m in MatchesToAddLater.Values) { AMatchDS.AEpMatch.Rows.Add(m); } AMatchDS.PBankingDetails.Clear(); AMatchDS.AGiftDetail.Clear(); AMatchDS.AGift.Clear(); AMatchDS.ThrowAwayAfterSubmitChanges = true; TLogging.LogAtLevel(1, "before submitchanges"); BankImportTDSAccess.SubmitChanges(AMatchDS); TLogging.LogAtLevel(1, "after submitchanges"); }
public static BankImportTDS GetBankStatementTransactionsAndMatches(Int32 AStatementKey, Int32 ALedgerNumber) { TDBTransaction Transaction = DBAccess.GDBAccessObj.BeginTransaction(IsolationLevel.Serializable); BankImportTDS ResultDataset = new BankImportTDS(); string MyClientID = DomainManager.GClientID.ToString(); TProgressTracker.InitProgressTracker(MyClientID, Catalog.GetString("Load Bank Statement"), 100.0m); TProgressTracker.SetCurrentState(MyClientID, Catalog.GetString("loading statement"), 0); try { AEpStatementAccess.LoadByPrimaryKey(ResultDataset, AStatementKey, Transaction); if (ResultDataset.AEpStatement[0].BankAccountCode.Length == 0) { throw new Exception("Loading Bank Statement: Bank Account must not be empty"); } ACostCentreAccess.LoadViaALedger(ResultDataset, ALedgerNumber, Transaction); AMotivationDetailAccess.LoadViaALedger(ResultDataset, ALedgerNumber, Transaction); AEpTransactionAccess.LoadViaAEpStatement(ResultDataset, AStatementKey, Transaction); BankImportTDS TempDataset = new BankImportTDS(); AEpTransactionAccess.LoadViaAEpStatement(TempDataset, AStatementKey, Transaction); AEpMatchAccess.LoadViaALedger(TempDataset, ResultDataset.AEpStatement[0].LedgerNumber, Transaction); // load all bankingdetails and partner shortnames related to this statement string sqlLoadPartnerByBankAccount = "SELECT DISTINCT p.p_partner_key_n AS PartnerKey, " + "p.p_partner_short_name_c AS ShortName, " + "t.p_branch_code_c AS BranchCode, " + "t.a_bank_account_number_c AS BankAccountNumber " + "FROM PUB_a_ep_transaction t, PUB_p_banking_details bd, PUB_p_bank b, PUB_p_partner_banking_details pbd, PUB_p_partner p " + "WHERE t.a_statement_key_i = " + AStatementKey.ToString() + " " + "AND bd.p_bank_account_number_c = t.a_bank_account_number_c " + "AND b.p_partner_key_n = bd.p_bank_key_n " + "AND b.p_branch_code_c = t.p_branch_code_c " + "AND pbd.p_banking_details_key_i = bd.p_banking_details_key_i " + "AND p.p_partner_key_n = pbd.p_partner_key_n"; DataTable PartnerByBankAccount = DBAccess.GDBAccessObj.SelectDT(sqlLoadPartnerByBankAccount, "partnerByBankAccount", Transaction); PartnerByBankAccount.DefaultView.Sort = "BranchCode, BankAccountNumber"; // get all recipients that have been merged string sqlGetMergedRecipients = string.Format( "SELECT DISTINCT p.p_partner_key_n AS PartnerKey, p.p_status_code_c AS StatusCode FROM PUB_a_ep_match m, PUB_p_partner p " + "WHERE (m.p_recipient_key_n = p.p_partner_key_n OR m.p_donor_key_n = p.p_partner_key_n) AND p.p_status_code_c = '{0}'", MPartnerConstants.PARTNERSTATUS_MERGED); DataTable MergedPartners = DBAccess.GDBAccessObj.SelectDT(sqlGetMergedRecipients, "mergedPartners", Transaction); MergedPartners.DefaultView.Sort = "PartnerKey"; DBAccess.GDBAccessObj.RollbackTransaction(); string BankAccountCode = ResultDataset.AEpStatement[0].BankAccountCode; TempDataset.AEpMatch.DefaultView.Sort = AEpMatchTable.GetMatchTextDBName(); SortedList <string, AEpMatchRow> MatchesToAddLater = new SortedList <string, AEpMatchRow>(); int count = 0; // load the matches or create new matches foreach (BankImportTDSAEpTransactionRow row in ResultDataset.AEpTransaction.Rows) { TProgressTracker.SetCurrentState(MyClientID, Catalog.GetString("finding matches") + " " + count + "/" + ResultDataset.AEpTransaction.Rows.Count.ToString(), 10.0m + (count * 80.0m / ResultDataset.AEpTransaction.Rows.Count)); count++; BankImportTDSAEpTransactionRow tempTransactionRow = (BankImportTDSAEpTransactionRow)TempDataset.AEpTransaction.Rows.Find( new object[] { row.StatementKey, row.Order, row.DetailKey }); // find a match with the same match text, or create a new one if (row.IsMatchTextNull() || (row.MatchText.Length == 0) || !row.MatchText.StartsWith(BankAccountCode)) { row.MatchText = TBankImportMatching.CalculateMatchText(BankAccountCode, row); tempTransactionRow.MatchText = row.MatchText; } DataRowView[] matches = TempDataset.AEpMatch.DefaultView.FindRows(row.MatchText); if (matches.Length > 0) { Decimal sum = 0.0m; // update the recent date foreach (DataRowView rv in matches) { AEpMatchRow r = (AEpMatchRow)rv.Row; sum += r.GiftTransactionAmount; // check if the recipient key is still valid. could be that they have married, and merged into another family record if ((r.RecipientKey != 0) && (MergedPartners.DefaultView.FindRows(r.RecipientKey).Length > 0)) { TLogging.LogAtLevel(1, "partner has been merged: " + r.RecipientKey.ToString()); r.RecipientKey = 0; r.Action = MFinanceConstants.BANK_STMT_STATUS_UNMATCHED; } // check if the donor key is still valid. could be that they have married, and merged into another family record if ((r.DonorKey != 0) && (MergedPartners.DefaultView.FindRows(r.DonorKey).Length > 0)) { TLogging.LogAtLevel(1, "partner has been merged: " + r.DonorKey.ToString()); r.DonorKey = 0; r.Action = MFinanceConstants.BANK_STMT_STATUS_UNMATCHED; } if (r.RecentMatch < row.DateEffective) { r.RecentMatch = row.DateEffective; } // do not modify tempRow.MatchAction, because that will not be stored in the database anyway, just costs time row.MatchAction = r.Action; if (r.IsDonorKeyNull() || (r.DonorKey <= 0)) { FindDonorByAccountNumber(r, PartnerByBankAccount.DefaultView, row.BranchCode, row.BankAccountNumber); } } if (sum != row.TransactionAmount) { TLogging.Log("we should drop this match since the total is wrong: " + row.Description); row.MatchAction = MFinanceConstants.BANK_STMT_STATUS_UNMATCHED; foreach (DataRowView rv in matches) { AEpMatchRow r = (AEpMatchRow)rv.Row; r.Action = MFinanceConstants.BANK_STMT_STATUS_UNMATCHED; } } } else if (!MatchesToAddLater.ContainsKey(row.MatchText)) { // create new match AEpMatchRow tempRow = TempDataset.AEpMatch.NewRowTyped(true); tempRow.EpMatchKey = (TempDataset.AEpMatch.Count + MatchesToAddLater.Count + 1) * -1; tempRow.Detail = 0; tempRow.MatchText = row.MatchText; tempRow.LedgerNumber = ALedgerNumber; tempRow.GiftTransactionAmount = row.TransactionAmount; tempRow.Action = MFinanceConstants.BANK_STMT_STATUS_UNMATCHED; FindDonorByAccountNumber(tempRow, PartnerByBankAccount.DefaultView, row.BranchCode, row.BankAccountNumber); #if disabled // fuzzy search for the partner. only return if unique result string sql = "SELECT p_partner_key_n, p_partner_short_name_c FROM p_partner WHERE p_partner_short_name_c LIKE '{0}%' OR p_partner_short_name_c LIKE '{1}%'"; string[] names = row.AccountName.Split(new char[] { ' ' }); if (names.Length > 1) { string optionShortName1 = names[0] + ", " + names[1]; string optionShortName2 = names[1] + ", " + names[0]; DataTable partner = DBAccess.GDBAccessObj.SelectDT(String.Format(sql, optionShortName1, optionShortName2), "partner", Transaction); if (partner.Rows.Count == 1) { tempRow.DonorKey = Convert.ToInt64(partner.Rows[0][0]); } } #endif MatchesToAddLater.Add(tempRow.MatchText, tempRow); // do not modify tempRow.MatchAction, because that will not be stored in the database anyway, just costs time row.MatchAction = tempRow.Action; } } // for speed reasons, add the new rows after clearing the sort on the view TempDataset.AEpMatch.DefaultView.Sort = string.Empty; foreach (AEpMatchRow m in MatchesToAddLater.Values) { TempDataset.AEpMatch.Rows.Add(m); } TProgressTracker.SetCurrentState(MyClientID, Catalog.GetString("save matches"), 90.0m); TempDataset.ThrowAwayAfterSubmitChanges = true; // only store a_ep_transactions and a_ep_matches, but without additional typed fields (ie MatchAction) BankImportTDSAccess.SubmitChanges(TempDataset.GetChangesTyped(true)); } catch (Exception e) { TLogging.Log(e.GetType().ToString() + " in BankImport, GetBankStatementTransactionsAndMatches; " + e.Message); TLogging.Log(e.StackTrace); DBAccess.GDBAccessObj.RollbackTransaction(); throw; } // drop all matches that do not occur on this statement ResultDataset.AEpMatch.Clear(); // reloading is faster than deleting all matches that are not needed string sqlLoadMatchesOfStatement = "SELECT DISTINCT m.* FROM PUB_a_ep_match m, PUB_a_ep_transaction t WHERE t.a_statement_key_i = ? AND m.a_ledger_number_i = ? AND m.a_match_text_c = t.a_match_text_c"; OdbcParameter param = new OdbcParameter("statementkey", OdbcType.Int); param.Value = AStatementKey; OdbcParameter paramLedgerNumber = new OdbcParameter("ledgerNumber", OdbcType.Int); paramLedgerNumber.Value = ALedgerNumber; DBAccess.GDBAccessObj.SelectDT(ResultDataset.AEpMatch, sqlLoadMatchesOfStatement, null, new OdbcParameter[] { param, paramLedgerNumber }, -1, -1); // update the custom field for cost centre name for each match foreach (BankImportTDSAEpMatchRow row in ResultDataset.AEpMatch.Rows) { ACostCentreRow ccRow = (ACostCentreRow)ResultDataset.ACostCentre.Rows.Find(new object[] { row.LedgerNumber, row.CostCentreCode }); if (ccRow != null) { row.CostCentreName = ccRow.CostCentreName; } } // remove all rows that we do not need on the client side ResultDataset.AGiftDetail.Clear(); ResultDataset.AMotivationDetail.Clear(); ResultDataset.ACostCentre.Clear(); ResultDataset.AcceptChanges(); if (TLogging.DebugLevel > 0) { int CountMatched = 0; foreach (BankImportTDSAEpTransactionRow transaction in ResultDataset.AEpTransaction.Rows) { if (!transaction.IsMatchActionNull() && (transaction.MatchAction != MFinanceConstants.BANK_STMT_STATUS_UNMATCHED)) { CountMatched++; } } TLogging.Log( "Loading bank statement: matched: " + CountMatched.ToString() + " of " + ResultDataset.AEpTransaction.Rows.Count.ToString()); } TProgressTracker.FinishJob(MyClientID); return(ResultDataset); }
/// <summary> /// store historic Gift matches /// </summary> private static void StoreCurrentMatches(BankImportTDS AMatchDS, string ABankAccountCode) { DataView GiftDetailView = new DataView( AMatchDS.AGiftDetail, string.Empty, BankImportTDSAGiftDetailTable.GetGiftTransactionNumberDBName() + "," + BankImportTDSAGiftDetailTable.GetDetailNumberDBName(), DataViewRowState.CurrentRows); SortedList <string, AEpMatchRow> MatchesToAddLater = new SortedList <string, AEpMatchRow>(); List <string> MatchesToDelete = new List <string>(); foreach (BankImportTDSAEpTransactionRow tr in AMatchDS.AEpTransaction.Rows) { // create a match text which uniquely identifies this transaction string MatchText = CalculateMatchText(ABankAccountCode, tr); // delete existing matches MatchesToDelete.Add(MatchText); if (tr.MatchAction != MFinanceConstants.BANK_STMT_STATUS_MATCHED) { continue; } // get the gift details assigned to this transaction StringCollection GiftDetailNumbers = StringHelper.GetCSVList(tr.GiftDetailNumbers, ",", false); foreach (string strDetailNumber in GiftDetailNumbers) { DataRowView[] FilteredGiftDetails = GiftDetailView.FindRows( new object[] { tr.GiftTransactionNumber, Convert.ToInt32(strDetailNumber) }); // add new matches // do not assign tr.EpMatchKey, because we cannot delete the old matches then CreateNewMatches( AMatchDS, (BankImportTDSAGiftDetailRow)FilteredGiftDetails[0].Row, MatchText, MatchesToAddLater); } } DataView MatchesByText = new DataView( AMatchDS.AEpMatch, string.Empty, AEpMatchTable.GetMatchTextDBName(), DataViewRowState.CurrentRows); foreach (string MatchToDelete in MatchesToDelete) { DataRowView[] MatchesToDeleteRv = MatchesByText.FindRows(MatchToDelete); foreach (DataRowView rv in MatchesToDeleteRv) { rv.Row.Delete(); } } MatchesByText.Sort = string.Empty; MatchesByText.RowFilter = string.Empty; // for speed reasons, add the new rows at the end foreach (AEpMatchRow m in MatchesToAddLater.Values) { AMatchDS.AEpMatch.Rows.Add(m); } AMatchDS.PBankingDetails.Clear(); AMatchDS.AGiftDetail.Clear(); AMatchDS.AGift.Clear(); AMatchDS.ThrowAwayAfterSubmitChanges = true; if (TLogging.DebugLevel > 0) { TLogging.Log("before submitchanges"); } BankImportTDSAccess.SubmitChanges(AMatchDS); if (TLogging.DebugLevel > 0) { TLogging.Log("after submitchanges"); } }