/// <summary> /// Update the specified Recurring Batch's LastJournal number. Assumes all necessary data is loaded for Batch /// </summary> /// <param name="AMainDS"></param> /// <param name="ACurrentBatchRow"></param> /// <param name="AIncludeJournals"></param> /// <returns>false if no change to batch totals</returns> public static bool UpdateRecurringBatchLastJournal(ref GLBatchTDS AMainDS, ref ARecurringBatchRow ACurrentBatchRow, Boolean AIncludeJournals = false) { #region Validate Arguments if (AMainDS == null) { throw new EFinanceSystemDataObjectNullOrEmptyException(String.Format(Catalog.GetString("Function:{0} - The GL Batch dataset is null!"), Utilities.GetMethodName(true))); } else if (ACurrentBatchRow == null) { throw new EFinanceSystemDataObjectNullOrEmptyException(String.Format(Catalog.GetString( "Function:{0} - The Recurring GL Batch data row is null!"), Utilities.GetMethodName(true))); } #endregion Validate Arguments bool RowUpdated = false; int ActualLastJournalNumber = 0; DataView JournalDV = new DataView(AMainDS.ARecurringJournal); JournalDV.RowFilter = String.Format("{0}={1}", ARecurringJournalTable.GetBatchNumberDBName(), ACurrentBatchRow.BatchNumber); //Highest Journal number first JournalDV.Sort = String.Format("{0} DESC", ARecurringJournalTable.GetJournalNumberDBName()); foreach (DataRowView journalView in JournalDV) { GLBatchTDSARecurringJournalRow journalRow = (GLBatchTDSARecurringJournalRow)journalView.Row; //Run once only if (ActualLastJournalNumber == 0) { ActualLastJournalNumber = journalRow.JournalNumber; } if (AIncludeJournals && UpdateRecurringJournalLastTransaction(ref AMainDS, ref journalRow)) { RowUpdated = true; } } if (ACurrentBatchRow.LastJournal != ActualLastJournalNumber) { ACurrentBatchRow.BeginEdit(); ACurrentBatchRow.LastJournal = ActualLastJournalNumber; ACurrentBatchRow.EndEdit(); RowUpdated = true; } return(RowUpdated); }
/// <summary> /// Calculate the base amount for the transactions, and update the totals for the journals and the current batch /// </summary> /// <param name="AMainDS"></param> /// <param name="ACurrentBatchRow"></param> /// <param name="ACurrentJournalNumber"></param> /// <returns>false if no change to batch totals</returns> public static bool UpdateRecurringBatchTotals(ref GLBatchTDS AMainDS, ref ARecurringBatchRow ACurrentBatchRow, Int32 ACurrentJournalNumber = 0) { #region Validate Arguments if (AMainDS == null) { throw new EFinanceSystemDataObjectNullOrEmptyException(String.Format(Catalog.GetString( "Function:{0} - The Recurring GL Batch dataset is null!"), Utilities.GetMethodName(true))); } else if (ACurrentBatchRow == null) { throw new EFinanceSystemDataObjectNullOrEmptyException(String.Format(Catalog.GetString( "Function:{0} - The Recurring GL Batch data row is null!"), Utilities.GetMethodName(true))); } #endregion Validate Arguments bool AmountsUpdated = false; decimal BatchDebitTotal = 0.0m; decimal BatchCreditTotal = 0.0m; DataView JournalDV = new DataView(AMainDS.ARecurringJournal); JournalDV.RowFilter = String.Format("{0}={1}", ARecurringJournalTable.GetBatchNumberDBName(), ACurrentBatchRow.BatchNumber); foreach (DataRowView journalView in JournalDV) { GLBatchTDSARecurringJournalRow journalRow = (GLBatchTDSARecurringJournalRow)journalView.Row; if (((ACurrentJournalNumber > 0) && (ACurrentJournalNumber == journalRow.JournalNumber)) || (ACurrentJournalNumber == 0)) { if ((UpdateRecurringJournalTotals(ref AMainDS, ref journalRow))) { AmountsUpdated = true; } } BatchDebitTotal += journalRow.JournalDebitTotal; BatchCreditTotal += journalRow.JournalCreditTotal; } if ((ACurrentBatchRow.BatchDebitTotal != BatchDebitTotal) || (ACurrentBatchRow.BatchCreditTotal != BatchCreditTotal)) { ACurrentBatchRow.BatchDebitTotal = BatchDebitTotal; ACurrentBatchRow.BatchCreditTotal = BatchCreditTotal; AmountsUpdated = true; } return(AmountsUpdated); }
/// <summary> /// Validates the Recurring GL Batch data. /// </summary> /// <param name="AContext">Context that describes where the data validation failed.</param> /// <param name="ARow">The <see cref="DataRow" /> which holds the the data against which the validation is run.</param> /// <param name="AVerificationResultCollection">Will be filled with any <see cref="TVerificationResult" /> items if /// data validation errors occur.</param> /// <returns>True if the validation found no data validation errors, otherwise false.</returns> public static bool ValidateRecurringGLBatchManual(object AContext, ARecurringBatchRow ARow, ref TVerificationResultCollection AVerificationResultCollection) { int VerifResultCollAddedCount = 0; //TODO return(VerifResultCollAddedCount == 0); }
private bool PreDeleteManual(ARecurringBatchRow ARowToDelete, ref string ADeletionQuestion) { bool allowDeletion = true; if (FPreviouslySelectedDetailRow != null) { ADeletionQuestion = String.Format(Catalog.GetString("Are you sure you want to delete recurring Batch {0}?"), ARowToDelete.BatchNumber); } return(allowDeletion); }
private void ParseHashTotal(ARecurringBatchRow ARow) { if ((txtDetailBatchControlTotal.NumberValueDecimal == null) || !txtDetailBatchControlTotal.NumberValueDecimal.HasValue) { bool prev = FPetraUtilsObject.SuppressChangeDetection; FPetraUtilsObject.SuppressChangeDetection = true; txtDetailBatchControlTotal.NumberValueDecimal = 0m; FPetraUtilsObject.SuppressChangeDetection = prev; } if (ARow.BatchControlTotal != txtDetailBatchControlTotal.NumberValueDecimal.Value) { ARow.BatchControlTotal = txtDetailBatchControlTotal.NumberValueDecimal.Value; } }
private void ParseHashTotal(ARecurringBatchRow ARow) { decimal correctHashValue = 0m; if ((txtDetailBatchControlTotal.NumberValueDecimal == null) || !txtDetailBatchControlTotal.NumberValueDecimal.HasValue) { correctHashValue = 0m; } else { correctHashValue = txtDetailBatchControlTotal.NumberValueDecimal.Value; } txtDetailBatchControlTotal.NumberValueDecimal = correctHashValue; ARow.BatchControlTotal = correctHashValue; }
/// <summary> /// Update the dictionary that stores all unposted batches /// and whether or not they have been warned about inactive /// fields /// </summary> /// <param name="ABatchNumberToExclude"></param> public void UpdateRecurringBatchDictionary(int ABatchNumberToExclude = 0) { if (ABatchNumberToExclude > 0) { FRecurringBatchesVerifiedOnSavingDict.Remove(ABatchNumberToExclude); } DataView BatchDV = new DataView(FMainDS.ARecurringBatch); foreach (DataRowView bRV in BatchDV) { ARecurringBatchRow br = (ARecurringBatchRow)bRV.Row; int currentBatch = br.BatchNumber; if ((currentBatch != ABatchNumberToExclude) && !FRecurringBatchesVerifiedOnSavingDict.ContainsKey(currentBatch)) { FRecurringBatchesVerifiedOnSavingDict.Add(br.BatchNumber, false); } } }
/// <summary> /// Calculate the base amount for the transactions, and update the totals for the journals and the current batch /// </summary> /// <param name="AMainDS"></param> /// <param name="ACurrentBatch"></param> public static void UpdateTotalsOfRecurringBatch(ref GLBatchTDS AMainDS, ARecurringBatchRow ACurrentBatch) { ACurrentBatch.BatchDebitTotal = 0.0m; ACurrentBatch.BatchCreditTotal = 0.0m; DataView jnlDataView = new DataView(AMainDS.ARecurringJournal); jnlDataView.RowFilter = String.Format("{0}={1}", ARecurringJournalTable.GetBatchNumberDBName(), ACurrentBatch.BatchNumber); foreach (DataRowView journalView in jnlDataView) { GLBatchTDSARecurringJournalRow journalRow = (GLBatchTDSARecurringJournalRow)journalView.Row; UpdateTotalsOfRecurringJournal(ref AMainDS, ref journalRow); ACurrentBatch.BatchDebitTotal += journalRow.JournalDebitTotal; ACurrentBatch.BatchCreditTotal += journalRow.JournalCreditTotal; } }
private void ShowDetailsManual(ARecurringBatchRow ARow) { AutoEnableTransTabForBatch(); grdDetails.TabStop = (ARow != null); if (ARow == null) { pnlDetails.Enabled = false; ((TFrmRecurringGLBatch)this.ParentForm).DisableJournals(); ((TFrmRecurringGLBatch)this.ParentForm).DisableTransactions(); EnableButtonControl(false); ClearControls(); return; } FPetraUtilsObject.DetailProtectedMode = false; FSelectedBatchNumber = ARow.BatchNumber; UpdateChangeableStatus(); ((TFrmRecurringGLBatch)this.ParentForm).EnableJournals(); }
private void ValidateDataDetailsManual(ARecurringBatchRow ARow) { if (ARow == null) { return; } TVerificationResultCollection VerificationResultCollection = FPetraUtilsObject.VerificationResultCollection; ParseHashTotal(ARow); TSharedFinanceValidation_GL.ValidateRecurringGLBatchManual(this, ARow, ref VerificationResultCollection, FValidationControlsDict); //TODO: remove this once database definition is set for Batch Description to be NOT NULL // Description is mandatory then make sure it is set if (txtDetailBatchDescription.Text.Length == 0) { DataColumn ValidationColumn; TVerificationResult VerificationResult = null; object ValidationContext; ValidationColumn = ARow.Table.Columns[ARecurringBatchTable.ColumnBatchDescriptionId]; ValidationContext = String.Format("Recurring Batch number {0}", ARow.BatchNumber); VerificationResult = TStringChecks.StringMustNotBeEmpty(ARow.BatchDescription, "Description of " + ValidationContext, this, ValidationColumn, null); // Handle addition/removal to/from TVerificationResultCollection VerificationResultCollection.Auto_Add_Or_AddOrRemove(this, VerificationResult, ValidationColumn, true); } }
/// <summary> /// Code to be run after the deletion process /// </summary> /// <param name="ARowToDelete">the row that was/was to be deleted</param> /// <param name="AAllowDeletion">whether or not the user was permitted to delete</param> /// <param name="ADeletionPerformed">whether or not the deletion was performed successfully</param> /// <param name="ACompletionMessage">if specified, is the deletion completion message</param> private void PostDeleteManual(ARecurringBatchRow ARowToDelete, bool AAllowDeletion, bool ADeletionPerformed, string ACompletionMessage) { /*Code to execute after the delete has occurred*/ TFrmRecurringGLBatch FMyForm = (TFrmRecurringGLBatch)this.ParentForm; try { if (ADeletionPerformed && (ACompletionMessage.Length > 0)) { UpdateChangeableStatus(); if (!pnlDetails.Enabled) //set by FocusedRowChanged if grdDetails.Rows.Count < 2 { ClearControls(); } FMyForm.SaveChangesManual(); //message to user MessageBox.Show(ACompletionMessage, "Deletion Successful", MessageBoxButtons.OK, MessageBoxIcon.Information); } ((TFrmRecurringGLBatch)ParentForm).EnableJournals((grdDetails.Rows.Count > 1)); SetInitialFocus(); } finally { FMyForm.FCurrentGLBatchAction = TGLBatchEnums.GLBatchAction.NONE; } }
/// <summary> /// Update the specified Recurring Batch's LastJournal number. Assumes all necessary data is loaded for Batch /// </summary> /// <param name="AMainDS"></param> /// <param name="ACurrentBatchRow"></param> /// <param name="AIncludeJournals"></param> /// <returns>false if no change to batch totals</returns> public static bool UpdateRecurringBatchLastJournal(ref GLBatchTDS AMainDS, ref ARecurringBatchRow ACurrentBatchRow, Boolean AIncludeJournals = false) { #region Validate Arguments if (AMainDS == null) { throw new EFinanceSystemDataObjectNullOrEmptyException(String.Format(Catalog.GetString("Function:{0} - The GL Batch dataset is null!"), Utilities.GetMethodName(true))); } else if (ACurrentBatchRow == null) { throw new EFinanceSystemDataObjectNullOrEmptyException(String.Format(Catalog.GetString( "Function:{0} - The Recurring GL Batch data row is null!"), Utilities.GetMethodName(true))); } #endregion Validate Arguments bool RowUpdated = false; int ActualLastJournalNumber = 0; DataView JournalDV = new DataView(AMainDS.ARecurringJournal); JournalDV.RowFilter = String.Format("{0}={1}", ARecurringJournalTable.GetBatchNumberDBName(), ACurrentBatchRow.BatchNumber); //Highest Journal number first JournalDV.Sort = String.Format("{0} DESC", ARecurringJournalTable.GetJournalNumberDBName()); foreach (DataRowView journalView in JournalDV) { GLBatchTDSARecurringJournalRow journalRow = (GLBatchTDSARecurringJournalRow)journalView.Row; //Run once only if (ActualLastJournalNumber == 0) { ActualLastJournalNumber = journalRow.JournalNumber; } if (AIncludeJournals && UpdateRecurringJournalLastTransaction(ref AMainDS, ref journalRow)) { RowUpdated = true; } } if (ACurrentBatchRow.LastJournal != ActualLastJournalNumber) { ACurrentBatchRow.LastJournal = ActualLastJournalNumber; RowUpdated = true; } return RowUpdated; }
private void ParseHashTotal(ARecurringBatchRow ARow) { decimal correctHashValue = 0m; if ((txtDetailBatchControlTotal.NumberValueDecimal == null) || !txtDetailBatchControlTotal.NumberValueDecimal.HasValue) { bool prev = FPetraUtilsObject.SuppressChangeDetection; FPetraUtilsObject.SuppressChangeDetection = true; txtDetailBatchControlTotal.NumberValueDecimal = correctHashValue; FPetraUtilsObject.SuppressChangeDetection = prev; } else { correctHashValue = txtDetailBatchControlTotal.NumberValueDecimal.Value; } ARow.BatchControlTotal = correctHashValue; }
private void ValidateDataDetailsManual(ARecurringTransactionRow ARow) { //Can be called from outside, so need to update fields FBatchRow = GetBatchRow(); if (FBatchRow == null) { return; } FJournalRow = GetJournalRow(); if (FJournalRow != null) { FJournalNumber = FJournalRow.JournalNumber; } if ((ARow == null) || (FBatchRow.BatchNumber != ARow.BatchNumber)) { return; } TVerificationResultCollection VerificationResultCollection = FPetraUtilsObject.VerificationResultCollection; Control controlToPass = null; //Local validation if (((txtDebitAmount.NumberValueDecimal.Value == 0) && (txtCreditAmount.NumberValueDecimal.Value == 0)) || (txtDebitAmount.NumberValueDecimal.Value < 0)) { controlToPass = txtDebitAmount; } else if (txtCreditAmount.NumberValueDecimal.Value < 0) { controlToPass = txtCreditAmount; } else if (TSystemDefaults.GetSystemDefault(SharedConstants.SYSDEFAULT_GLREFMANDATORY, "no") == "yes") { controlToPass = txtDetailReference; } else if ((VerificationResultCollection.Count == 1) && (VerificationResultCollection[0].ResultCode == CommonErrorCodes.ERR_INVALIDNUMBER)) { //The amount controls register as invalid even when value is correct. Need to reset // Verifications accordingly. FPetraUtilsObject.VerificationResultCollection.Clear(); } TSharedFinanceValidation_GL.ValidateRecurringGLDetailManual(this, FBatchRow, ARow, controlToPass, ref VerificationResultCollection, FValidationControlsDict); if ((FPreviouslySelectedDetailRow != null) && !FAnalysisAttributesLogic.AccountRecurringAnalysisAttributeCountIsCorrect( FPreviouslySelectedDetailRow.TransactionNumber, FPreviouslySelectedDetailRow.AccountCode, FMainDS)) { DataColumn ValidationColumn; TVerificationResult VerificationResult = null; object ValidationContext; ValidationColumn = ARow.Table.Columns[ARecurringTransactionTable.ColumnAccountCodeId]; ValidationContext = "unused because of OverrideResultText"; // This code is only running because of failure, so cause an error to occur. VerificationResult = TStringChecks.StringMustNotBeEmpty("", ValidationContext.ToString(), this, ValidationColumn, null); VerificationResult.OverrideResultText(String.Format( "A value must be entered for 'Analysis Attributes' for Account Code {0} in Transaction {1}.", ARow.AccountCode, ARow.TransactionNumber)); // Handle addition/removal to/from TVerificationResultCollection VerificationResultCollection.Auto_Add_Or_AddOrRemove(this, VerificationResult, ValidationColumn, true); } String ValueRequiredForType; if ((FPreviouslySelectedDetailRow != null) && !FAnalysisAttributesLogic.AccountRecurringAnalysisAttributesValuesExist( FPreviouslySelectedDetailRow.TransactionNumber, FPreviouslySelectedDetailRow.AccountCode, FMainDS, out ValueRequiredForType)) { DataColumn ValidationColumn; TVerificationResult VerificationResult = null; object ValidationContext; ValidationColumn = ARow.Table.Columns[ARecurringTransactionTable.ColumnAccountCodeId]; ValidationContext = String.Format("Analysis code {0} for Account Code {1} in Transaction {2}", ValueRequiredForType, ARow.AccountCode, ARow.TransactionNumber); // This code is only running because of failure, so cause an error to occur. VerificationResult = TStringChecks.StringMustNotBeEmpty("", ValidationContext.ToString(), this, ValidationColumn, null); // Handle addition/removal to/from TVerificationResultCollection VerificationResultCollection.Auto_Add_Or_AddOrRemove(this, VerificationResult, ValidationColumn, true); } }
/// <summary> /// Deletes the current row and optionally populates a completion message /// </summary> /// <param name="ARowToDelete">the currently selected row to delete</param> /// <param name="ACompletionMessage">if specified, is the deletion completion message</param> /// <returns>true if row deletion is successful</returns> private bool DeleteRowManual(ARecurringBatchRow ARowToDelete, ref string ACompletionMessage) { //Assign default value(s) bool DeletionSuccessful = false; if (ARowToDelete == null) { return DeletionSuccessful; } int BatchNumber = ARowToDelete.BatchNumber; //Backup the Dataset for reversion purposes GLBatchTDS BackupMainDS = (GLBatchTDS)FMainDS.Copy(); BackupMainDS.Merge(FMainDS); if (ARowToDelete.RowState != DataRowState.Added) { //Reject any changes which may fail validation ARowToDelete.RejectChanges(); ShowDetails(ARowToDelete); } try { this.Cursor = Cursors.WaitCursor; ACompletionMessage = String.Format(Catalog.GetString("Batch no.: {0} deleted successfully."), BatchNumber); // Delete the associated recurring transaction analysis attributes DataView viewRecurringTransAnalAttrib = new DataView(FMainDS.ARecurringTransAnalAttrib); viewRecurringTransAnalAttrib.RowFilter = String.Format("{0}={1} AND {2}={3}", ARecurringTransAnalAttribTable.GetLedgerNumberDBName(), FLedgerNumber, ARecurringTransAnalAttribTable.GetBatchNumberDBName(), BatchNumber); foreach (DataRowView row in viewRecurringTransAnalAttrib) { row.Delete(); } // Delete the associated recurring transactions DataView viewRecurringTransaction = new DataView(FMainDS.ARecurringTransaction); viewRecurringTransaction.RowFilter = String.Format("{0}={1} AND {2}={3}", ARecurringTransactionTable.GetLedgerNumberDBName(), FLedgerNumber, ARecurringTransactionTable.GetBatchNumberDBName(), BatchNumber); foreach (DataRowView row in viewRecurringTransaction) { row.Delete(); } // Delete the associated recurring journals DataView viewRecurringJournal = new DataView(FMainDS.ARecurringJournal); viewRecurringJournal.RowFilter = String.Format("{0}={1} AND {2}={3}", ARecurringJournalTable.GetLedgerNumberDBName(), FLedgerNumber, ARecurringJournalTable.GetBatchNumberDBName(), BatchNumber); foreach (DataRowView row in viewRecurringJournal) { row.Delete(); } // Delete the recurring batch row. ARowToDelete.Delete(); DeletionSuccessful = true; } catch (Exception ex) { ACompletionMessage = ex.Message; MessageBox.Show(ACompletionMessage, "Deletion Error", MessageBoxButtons.OK, MessageBoxIcon.Error); //Revert to previous state FMainDS.Merge(BackupMainDS); } finally { this.Cursor = Cursors.Default; } UpdateRecordNumberDisplay(); return DeletionSuccessful; }
/// <summary> /// load the journals into the grid /// </summary> /// <param name="ACurrentBatchRow"></param> public void LoadJournals(ARecurringBatchRow ACurrentBatchRow) { FJournalsLoaded = false; FBatchRow = ACurrentBatchRow; if (FBatchRow == null) { return; } Int32 CurrentLedgerNumber = ACurrentBatchRow.LedgerNumber; Int32 CurrentBatchNumber = ACurrentBatchRow.BatchNumber; bool FirstRun = (FLedgerNumber != CurrentLedgerNumber); bool BatchChanged = (FBatchNumber != CurrentBatchNumber); if (FirstRun) { FLedgerNumber = CurrentLedgerNumber; } if (BatchChanged) { FBatchNumber = CurrentBatchNumber; } //Check if same Journals as previously selected if (!(FirstRun || BatchChanged)) { //Need to reconnect FPrev in some circumstances if (FPreviouslySelectedDetailRow == null) { DataRowView rowView = (DataRowView)grdDetails.Rows.IndexToDataSourceRow(FPrevRowChangedRow); if (rowView != null) { FPreviouslySelectedDetailRow = (GLBatchTDSARecurringJournalRow)(rowView.Row); } } if (GetSelectedRowIndex() > 0) { GetDetailsFromControls(GetSelectedDetailRow()); } } else { // a different journal SetJournalDefaultView(); FPreviouslySelectedDetailRow = null; //Load Journals if (FMainDS.ARecurringJournal.DefaultView.Count == 0) { FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadARecurringJournal(FLedgerNumber, FBatchNumber)); } //Ensure Last Batch Number is correct, needed to correct old Petra data if ((FBatchRow.LastJournal != FMainDS.ARecurringJournal.DefaultView.Count) && GLRoutines.UpdateRecurringBatchLastJournal(ref FMainDS, ref FBatchRow)) { FPetraUtilsObject.SetChangedFlag(); } ShowData(); // Now set up the complete current filter FFilterAndFindObject.FilterPanelControls.SetBaseFilter(FMainDS.ARecurringJournal.DefaultView.RowFilter, true); FFilterAndFindObject.ApplyFilter(); } int nRowToSelect = (BatchChanged || FirstRun) ? 1 : FPrevRowChangedRow; //This will also call UpdateChangeableStatus SelectRowInGrid(nRowToSelect); UpdateRecordNumberDisplay(); FFilterAndFindObject.SetRecordNumberDisplayProperties(); //Check for incorrect Exchange rate to base foreach (DataRowView drv in FMainDS.ARecurringJournal.DefaultView) { ARecurringJournalRow rjr = (ARecurringJournalRow)drv.Row; if (rjr.ExchangeRateToBase == 0) { rjr.ExchangeRateToBase = 1; FPetraUtilsObject.HasChanges = true; } } FJournalsLoaded = true; //Check on batch totals if (GLRoutines.UpdateRecurringBatchTotals(ref FMainDS, ref FBatchRow)) { FPetraUtilsObject.SetChangedFlag(); } }
/// <summary> /// Undo all changes to the specified batch ready to cancel it. /// This avoids unecessary validation errors when cancelling. /// </summary> /// <param name="ABatchToDelete"></param> /// <param name="ARedisplay"></param> public void PrepareBatchDataForDeleting(Int32 ABatchToDelete, Boolean ARedisplay) { //This code will only be called when the Batch tab is active. DataView GLBatchDV = new DataView(FMainDS.ARecurringBatch); DataView JournalDV = new DataView(FMainDS.ARecurringJournal); DataView TransDV = new DataView(FMainDS.ARecurringTransaction); DataView TransAnalDV = new DataView(FMainDS.ARecurringTransAnalAttrib); GLBatchDV.RowFilter = String.Format("{0}={1}", ARecurringBatchTable.GetBatchNumberDBName(), ABatchToDelete); JournalDV.RowFilter = String.Format("{0}={1}", ARecurringJournalTable.GetBatchNumberDBName(), ABatchToDelete); TransDV.RowFilter = String.Format("{0}={1}", ARecurringTransactionTable.GetBatchNumberDBName(), ABatchToDelete); TransAnalDV.RowFilter = String.Format("{0}={1}", ARecurringTransAnalAttribTable.GetBatchNumberDBName(), ABatchToDelete); //Work from lowest level up if (TransAnalDV.Count > 0) { TransAnalDV.Sort = String.Format("{0}, {1}, {2}", ARecurringTransAnalAttribTable.GetJournalNumberDBName(), ARecurringTransAnalAttribTable.GetTransactionNumberDBName(), ARecurringTransAnalAttribTable.GetAnalysisTypeCodeDBName()); foreach (DataRowView drv in TransAnalDV) { ARecurringTransAnalAttribRow transAnalRow = (ARecurringTransAnalAttribRow)drv.Row; if (transAnalRow.RowState == DataRowState.Added) { //Do nothing } else if (transAnalRow.RowState != DataRowState.Unchanged) { transAnalRow.RejectChanges(); } } } if (TransDV.Count > 0) { TransDV.Sort = String.Format("{0}, {1}", ARecurringTransactionTable.GetJournalNumberDBName(), ARecurringTransactionTable.GetTransactionNumberDBName()); foreach (DataRowView drv in TransDV) { ARecurringTransactionRow transRow = (ARecurringTransactionRow)drv.Row; if (transRow.RowState == DataRowState.Added) { //Do nothing } else if (transRow.RowState != DataRowState.Unchanged) { transRow.RejectChanges(); } } } if (JournalDV.Count > 0) { JournalDV.Sort = String.Format("{0}", ARecurringJournalTable.GetJournalNumberDBName()); foreach (DataRowView drv in JournalDV) { ARecurringJournalRow journalRow = (ARecurringJournalRow)drv.Row; if (journalRow.RowState == DataRowState.Added) { //Do nothing } else if (journalRow.RowState != DataRowState.Unchanged) { journalRow.RejectChanges(); } } } if (GLBatchDV.Count > 0) { ARecurringBatchRow batchRow = (ARecurringBatchRow)GLBatchDV[0].Row; //No need to check for Added state as new batches are always saved // on creation if (batchRow.RowState != DataRowState.Unchanged) { batchRow.RejectChanges(); } if (ARedisplay) { ShowDetails(batchRow); } } if (TransDV.Count == 0) { //Load all related data for batch ready to delete/cancel FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadARecurringJournalAndRelatedTablesForBatch(FLedgerNumber, ABatchToDelete)); } }
/// <summary> /// load the journals into the grid /// </summary> /// <param name="ALedgerNumber"></param> /// <param name="ABatchNumber"></param> public void LoadJournals(Int32 ALedgerNumber, Int32 ABatchNumber) { bool FirstRun = (FLedgerNumber != ALedgerNumber); bool BatchChanged = (FBatchNumber != ABatchNumber); FJournalsLoaded = false; FBatchRow = GetBatchRow(); if (FBatchRow == null) { return; } //Check if same Journals as previously selected if (!FirstRun && !BatchChanged) { if (GetSelectedRowIndex() > 0) { GetDetailsFromControls(GetSelectedDetailRow()); } } else { // a different journal FLedgerNumber = ALedgerNumber; FBatchNumber = ABatchNumber; SetJournalDefaultView(); FPreviouslySelectedDetailRow = null; if (FMainDS.ARecurringJournal.DefaultView.Count == 0) { FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadARecurringJournalAndContent(ALedgerNumber, ABatchNumber)); } ShowData(); // Now set up the complete current filter FFilterAndFindObject.ApplyFilter(); } //Check for incorrect Exchange rate to base foreach (DataRowView drv in FMainDS.ARecurringJournal.DefaultView) { ARecurringJournalRow rjr = (ARecurringJournalRow)drv.Row; if (rjr.ExchangeRateToBase == 0) { rjr.ExchangeRateToBase = 1; FPetraUtilsObject.HasChanges = true; } } FJournalsLoaded = true; //This will also call UpdateChangeableStatus SelectRowInGrid((BatchChanged || FirstRun) ? 1 : FPrevRowChangedRow); UpdateRecordNumberDisplay(); FFilterAndFindObject.SetRecordNumberDisplayProperties(); }
/// <summary> /// Code to be run after the deletion process /// </summary> /// <param name="ARowToDelete">the row that was/was to be deleted</param> /// <param name="AAllowDeletion">whether or not the user was permitted to delete</param> /// <param name="ADeletionPerformed">whether or not the deletion was performed successfully</param> /// <param name="ACompletionMessage">if specified, is the deletion completion message</param> private void PostDeleteManual(ARecurringBatchRow ARowToDelete, bool AAllowDeletion, bool ADeletionPerformed, string ACompletionMessage) { /*Code to execute after the delete has occurred*/ if (ADeletionPerformed && (ACompletionMessage.Length > 0)) { //causes saving issues //UpdateLedgerTableSettings(); ((TFrmRecurringGLBatch) this.ParentForm).SaveChanges(); MessageBox.Show(ACompletionMessage, Catalog.GetString("Deletion Completed")); } UpdateChangeableStatus(); if (!pnlDetails.Enabled) //set by FocusedRowChanged if grdDetails.Rows.Count < 2 { ClearControls(); } if (grdDetails.Rows.Count > 1) { ((TFrmRecurringGLBatch)ParentForm).EnableJournals(); } else { ((TFrmRecurringGLBatch)ParentForm).GetJournalsControl().ClearCurrentSelection(); ((TFrmRecurringGLBatch)ParentForm).DisableJournals(); } SetInitialFocus(); }
/// <summary> /// Deletes the current row and optionally populates a completion message /// </summary> /// <param name="ARowToDelete">the currently selected row to delete</param> /// <param name="ACompletionMessage">if specified, is the deletion completion message</param> /// <returns>true if row deletion is successful</returns> private bool DeleteRowManual(ARecurringBatchRow ARowToDelete, ref string ACompletionMessage) { int BatchNumber = ARowToDelete.BatchNumber; // Delete on client side data through views that is already loaded. Data that is not // loaded yet will be deleted with cascading delete on server side so we don't have // to worry about this here. ACompletionMessage = String.Format(Catalog.GetString("Batch no.: {0} deleted successfully."), BatchNumber); // Delete the associated recurring transaction analysis attributes DataView viewRecurringTransAnalAttrib = new DataView(FMainDS.ARecurringTransAnalAttrib); viewRecurringTransAnalAttrib.RowFilter = String.Format("{0} = {1} AND {2} = {3}", ARecurringTransAnalAttribTable.GetLedgerNumberDBName(), FLedgerNumber, ARecurringTransAnalAttribTable.GetBatchNumberDBName(), BatchNumber); foreach (DataRowView row in viewRecurringTransAnalAttrib) { row.Delete(); } // Delete the associated recurring transactions DataView viewRecurringTransaction = new DataView(FMainDS.ARecurringTransaction); viewRecurringTransaction.RowFilter = String.Format("{0} = {1} AND {2} = {3}", ARecurringTransactionTable.GetLedgerNumberDBName(), FLedgerNumber, ARecurringTransactionTable.GetBatchNumberDBName(), BatchNumber); foreach (DataRowView row in viewRecurringTransaction) { row.Delete(); } // Delete the associated recurring journals DataView viewRecurringJournal = new DataView(FMainDS.ARecurringJournal); viewRecurringJournal.RowFilter = String.Format("{0} = {1} AND {2} = {3}", ARecurringJournalTable.GetLedgerNumberDBName(), FLedgerNumber, ARecurringJournalTable.GetBatchNumberDBName(), BatchNumber); foreach (DataRowView row in viewRecurringJournal) { row.Delete(); } // Delete the recurring batch row. ARowToDelete.Delete(); UpdateRecordNumberDisplay(); return true; }
private bool PreDeleteManual(ARecurringBatchRow ARowToDelete, ref string ADeletionQuestion) { bool allowDeletion = true; if (FPreviouslySelectedDetailRow != null) { ADeletionQuestion = String.Format(Catalog.GetString("Are you sure you want to delete recurring Batch {0}?"), ARowToDelete.BatchNumber); } return allowDeletion; }
private void ShowDetailsManual(ARecurringBatchRow ARow) { AutoEnableTransTabForBatch(); grdDetails.TabStop = (ARow != null); if (ARow == null) { pnlDetails.Enabled = false; ((TFrmRecurringGLBatch) this.ParentForm).DisableJournals(); ((TFrmRecurringGLBatch) this.ParentForm).DisableTransactions(); EnableButtonControl(false); ClearControls(); return; } FPetraUtilsObject.DetailProtectedMode = false; FSelectedBatchNumber = ARow.BatchNumber; UpdateChangeableStatus(); ((TFrmRecurringGLBatch) this.ParentForm).EnableJournals(); }
/// <summary> /// Validates the recurring GL Detail data. /// </summary> /// <param name="AContext">Context that describes where the data validation failed.</param> /// <param name="ABatchRow">Manually added to bring over some GL Batch fields</param> /// <param name="ARow">The <see cref="DataRow" /> which holds the the data against which the validation is run.</param> /// <param name="AControl"></param> /// <param name="AVerificationResultCollection">Will be filled with any <see cref="TVerificationResult" /> items if /// data validation errors occur.</param> /// <param name="AValidationControlsDict">A <see cref="TValidationControlsDict" /> containing the Controls that /// display data that is about to be validated.</param> /// <returns>True if the validation found no data validation errors, otherwise false.</returns> public static bool ValidateRecurringGLDetailManual(object AContext, ARecurringBatchRow ABatchRow, ARecurringTransactionRow ARow, Control AControl, ref TVerificationResultCollection AVerificationResultCollection, TValidationControlsDict AValidationControlsDict) { DataColumn ValidationColumn; TValidationControlsData ValidationControlsData; TVerificationResult VerificationResult = null; object ValidationContext; int VerifResultCollAddedCount = 0; // Don't validate deleted DataRows if (ARow.RowState == DataRowState.Deleted) { return true; } //TransactionAmount is not in the dictionary so had to pass the control directly // also needed to handle reference if ((AControl != null) && AControl.Name.EndsWith("Amount")) { // 'GL amount must be non-zero ValidationColumn = ARow.Table.Columns[ARecurringTransactionTable.ColumnTransactionAmountId]; ValidationContext = String.Format("Transaction number {0} (batch:{1} journal:{2})", ARow.TransactionNumber, ARow.BatchNumber, ARow.JournalNumber); VerificationResult = TNumericalChecks.IsPositiveDecimal(ARow.TransactionAmount, "Amount of " + ValidationContext, AContext, ValidationColumn, AControl); if (VerificationResult != null) { VerificationResult.SuppressValidationToolTip = true; } // Handle addition/removal to/from TVerificationResultCollection if (AVerificationResultCollection.Auto_Add_Or_AddOrRemove(AContext, VerificationResult, ValidationColumn, true)) { VerifResultCollAddedCount++; } return VerifResultCollAddedCount == 0; } // Narrative must not be empty ValidationColumn = ARow.Table.Columns[ARecurringTransactionTable.ColumnNarrativeId]; ValidationContext = String.Format("Transaction number {0} (batch:{1} journal:{2})", ARow.TransactionNumber, ARow.BatchNumber, ARow.JournalNumber); if (AValidationControlsDict.TryGetValue(ValidationColumn, out ValidationControlsData)) { VerificationResult = TStringChecks.StringMustNotBeEmpty(ARow.Narrative, "Narrative of " + ValidationContext, AContext, ValidationColumn, ValidationControlsData.ValidationControl); // Handle addition/removal to/from TVerificationResultCollection if (AVerificationResultCollection.Auto_Add_Or_AddOrRemove(AContext, VerificationResult, ValidationColumn, true)) { VerifResultCollAddedCount++; } } if ((AControl != null) && AControl.Name.EndsWith("Reference")) { ValidationColumn = ARow.Table.Columns[ARecurringTransactionTable.ColumnReferenceId]; ValidationContext = String.Format("Transaction number {0} (batch:{1} journal:{2})", ARow.TransactionNumber, ARow.BatchNumber, ARow.JournalNumber); if (AValidationControlsDict.TryGetValue(ValidationColumn, out ValidationControlsData)) { VerificationResult = TStringChecks.StringMustNotBeEmpty(ARow.Reference, "Reference of " + ValidationContext, AContext, ValidationColumn, ValidationControlsData.ValidationControl); // Handle addition/removal to/from TVerificationResultCollection if (AVerificationResultCollection.Auto_Add_Or_AddOrRemove(AContext, VerificationResult, ValidationColumn, true)) { VerifResultCollAddedCount++; } } } return VerifResultCollAddedCount == 0; }
/// <summary> /// load the transactions into the grid /// </summary> /// <param name="ALedgerNumber"></param> /// <param name="ABatchNumber"></param> /// <param name="AJournalNumber"></param> /// <param name="ACurrencyCode"></param> /// <param name="AFromBatchTab"></param> /// <returns>True if new GL transactions were loaded, false if transactions had been loaded already.</returns> public bool LoadRecurringTransactions(Int32 ALedgerNumber, Int32 ABatchNumber, Int32 AJournalNumber, string ACurrencyCode, bool AFromBatchTab = false) { bool DifferentBatchSelected = false; bool HadChangesFromTheStart = FPetraUtilsObject.HasChanges; FLoadCompleted = false; FBatchRow = GetRecurringBatchRow(); FJournalRow = GetRecurringJournalRow(); if (FLedgerNumber == -1) { InitialiseControls(); } //Check if the same batch is selected, so no need to apply filter if ((FLedgerNumber == ALedgerNumber) && (FBatchNumber == ABatchNumber) && (FJournalNumber == AJournalNumber) && (FTransactionCurrency == ACurrencyCode) && (FMainDS.ARecurringTransaction.DefaultView.Count > 0)) { //Same as previously selected if (GetSelectedRowIndex() > 0) { if (AFromBatchTab) { SelectRowInGrid(GetSelectedRowIndex()); } else { GetDetailsFromControls(GetSelectedDetailRow()); } } FLoadCompleted = true; } else { // Different batch DifferentBatchSelected = true; bool requireControlSetup = (FLedgerNumber == -1) || (FTransactionCurrency != ACurrencyCode); FLedgerNumber = ALedgerNumber; FBatchNumber = ABatchNumber; FJournalNumber = AJournalNumber; FTransactionNumber = -1; FTransactionCurrency = ACurrencyCode; FPreviouslySelectedDetailRow = null; grdDetails.SuspendLayout(); //Empty grids before filling them grdDetails.DataSource = null; grdAnalAttributes.DataSource = null; // This sets the main part of the filter but excluding the additional items set by the user GUI // It gets the right sort order SetTransactionDefaultView(); //Load from server if necessary if (FMainDS.ARecurringTransaction.DefaultView.Count == 0) { FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadARecurringTransactionARecurringTransAnalAttrib(ALedgerNumber, ABatchNumber, AJournalNumber)); } // We need to call this because we have not called ShowData(), which would have set it. This differs from the Gift screen. grdDetails.DataSource = new DevAge.ComponentModel.BoundDataView(FMainDS.ARecurringTransaction.DefaultView); // Now we set the full filter FFilterAndFindObject.ApplyFilter(); if (grdAnalAttributes.Columns.Count == 1) { grdAnalAttributes.SpecialKeys = GridSpecialKeys.Default | GridSpecialKeys.Tab; FcmbAnalAttribValues = new SourceGrid.Cells.Editors.ComboBox(typeof(string)); FcmbAnalAttribValues.EnableEdit = true; FcmbAnalAttribValues.EditableMode = EditableMode.Focus; grdAnalAttributes.AddTextColumn("Value", FMainDS.ARecurringTransAnalAttrib.Columns[ARecurringTransAnalAttribTable.GetAnalysisAttributeValueDBName()], 100, FcmbAnalAttribValues); FcmbAnalAttribValues.Control.SelectedValueChanged += new EventHandler(this.AnalysisAttributeValueChanged); grdAnalAttributes.Columns[0].Width = 99; } FAnalysisAttributesLogic = new TAnalysisAttributes(FLedgerNumber, FBatchNumber, FJournalNumber); FAnalysisAttributesLogic.SetRecurringTransAnalAttributeDefaultView(FMainDS); FMainDS.ARecurringTransAnalAttrib.DefaultView.AllowNew = false; grdAnalAttributes.DataSource = new DevAge.ComponentModel.BoundDataView(FMainDS.ARecurringTransAnalAttrib.DefaultView); grdAnalAttributes.SetHeaderTooltip(0, Catalog.GetString("Type")); grdAnalAttributes.SetHeaderTooltip(1, Catalog.GetString("Value")); //Always show active and inactive values if (requireControlSetup) { //Load all analysis attribute values if (FCacheDS == null) { FCacheDS = TRemote.MFinance.GL.WebConnectors.LoadAAnalysisAttributes(FLedgerNumber, FActiveOnly); } SetupExtraGridFunctionality(); TFinanceControls.InitialiseAccountList(ref cmbDetailAccountCode, FLedgerNumber, true, false, FActiveOnly, false, ACurrencyCode, true); TFinanceControls.InitialiseCostCentreList(ref cmbDetailCostCentreCode, FLedgerNumber, true, false, FActiveOnly, false); } // This modifies the content of the text boxes that display the totals. This is not a user change. bool prev = FPetraUtilsObject.SuppressChangeDetection; FPetraUtilsObject.SuppressChangeDetection = true; UpdateTransactionTotals(); FPetraUtilsObject.SuppressChangeDetection = prev; grdDetails.ResumeLayout(); FLoadCompleted = true; } //Check for incorrect Exchange rate to base (mainly for existing Petra data) foreach (DataRowView drv in FMainDS.ARecurringTransaction.DefaultView) { ARecurringTransactionRow rtr = (ARecurringTransactionRow)drv.Row; if (rtr.ExchangeRateToBase == 0) { rtr.ExchangeRateToBase = 1; FPetraUtilsObject.HasChanges = true; } } if (FPetraUtilsObject.HasChanges && !HadChangesFromTheStart) { // This means we updated the transaction totals. We will save them behind the scenes since there were no other changes when we started ((TFrmRecurringGLBatch)ParentForm).SaveChanges(); FMainDS.ARecurringTransaction.AcceptChanges(); } ShowData(); SelectRowInGrid(1); ShowDetails(); //Needed because of how currency is handled UpdateChangeableStatus(); UpdateRecordNumberDisplay(); FFilterAndFindObject.SetRecordNumberDisplayProperties(); return DifferentBatchSelected; }
/// <summary> /// Validates the Recurring GL Batch data. /// </summary> /// <param name="AContext">Context that describes where the data validation failed.</param> /// <param name="ARow">The <see cref="DataRow" /> which holds the the data against which the validation is run.</param> /// <param name="AVerificationResultCollection">Will be filled with any <see cref="TVerificationResult" /> items if /// data validation errors occur.</param> /// <param name="AValidationControlsDict">A <see cref="TValidationControlsDict" /> containing the Controls that /// display data that is about to be validated.</param> /// <returns>True if the validation found no data validation errors, otherwise false.</returns> public static bool ValidateRecurringGLBatchManual(object AContext, ARecurringBatchRow ARow, ref TVerificationResultCollection AVerificationResultCollection, TValidationControlsDict AValidationControlsDict) { int VerifResultCollAddedCount = 0; //TODO return VerifResultCollAddedCount == 0; }
/// <summary> /// Load Journals for current Batch /// </summary> /// <param name="ACurrentBatchRow"></param> public void LoadJournals(ARecurringBatchRow ACurrentBatchRow) { this.ucoRecurringJournals.LoadJournals(ACurrentBatchRow); }
/// <summary> /// Deletes the current row and optionally populates a completion message /// </summary> /// <param name="ARowToDelete">the currently selected row to delete</param> /// <param name="ACompletionMessage">if specified, is the deletion completion message</param> /// <returns>true if row deletion is successful</returns> private bool DeleteRowManual(ARecurringBatchRow ARowToDelete, ref string ACompletionMessage) { bool DeletionSuccessful = false; ACompletionMessage = string.Empty; if (ARowToDelete == null) { return(false); } //Notify of deletion process TFrmRecurringGLBatch MainForm = (TFrmRecurringGLBatch)this.ParentForm; int CurrentBatchNumber = ARowToDelete.BatchNumber; bool CurrentBatchJournalsLoadedAndCurrent = false; bool CurrentBatchTransactionsLoadedAndCurrent = false; //Backup the Dataset for reversion purposes GLBatchTDS BackupMainDS = null; //Reject any changes which may fail validation ARowToDelete.RejectChanges(); ShowDetails(ARowToDelete); try { this.Cursor = Cursors.WaitCursor; MainForm.FCurrentGLBatchAction = TGLBatchEnums.GLBatchAction.DELETING; //Backup the changes to allow rollback BackupMainDS = (GLBatchTDS)FMainDS.GetChangesTyped(false); //Don't run an inactive fields check on this batch MainForm.GetBatchControl().UpdateRecurringBatchDictionary(CurrentBatchNumber); //Check if current batch journals and transactions are loaded and being viewed in their tab CurrentBatchJournalsLoadedAndCurrent = (MainForm.GetJournalsControl().FBatchNumber == CurrentBatchNumber); CurrentBatchTransactionsLoadedAndCurrent = (MainForm.GetTransactionsControl().FBatchNumber == CurrentBatchNumber); //Save and check for inactive values FPetraUtilsObject.SetChangedFlag(); if (!MainForm.SaveChangesManual(MainForm.FCurrentGLBatchAction, !CurrentBatchJournalsLoadedAndCurrent, !CurrentBatchTransactionsLoadedAndCurrent)) { MainForm.GetBatchControl().UpdateRecurringBatchDictionary(); string msg = String.Format(Catalog.GetString("Recurring Batch {0} has not been deleted."), CurrentBatchNumber); MessageBox.Show(msg, Catalog.GetString("Recurring GL Batch Deletion"), MessageBoxButtons.OK, MessageBoxIcon.Information); return(false); } //Remove any changes to current batch that may cause validation issues PrepareBatchDataForDeleting(CurrentBatchNumber, true); //Clear the journal and trans tabs if current batch data is displayed there if (CurrentBatchJournalsLoadedAndCurrent) { //Clear any transactions currently being edited in the Transaction Tab MainForm.GetJournalsControl().ClearCurrentSelection(CurrentBatchNumber); } if (CurrentBatchTransactionsLoadedAndCurrent) { //Clear any transactions currently being edited in the Transaction Tab MainForm.GetTransactionsControl().ClearCurrentSelection(CurrentBatchNumber); } //Delete transactions MainForm.GetTransactionsControl().DeleteRecurringTransactionData(CurrentBatchNumber); //Delete Journals MainForm.GetJournalsControl().DeleteRecurringJournalData(CurrentBatchNumber); // Delete the recurring batch row. ARowToDelete.Delete(); ACompletionMessage = String.Format(Catalog.GetString("Recurring Batch no.: {0} deleted successfully."), CurrentBatchNumber); DeletionSuccessful = true; } catch (Exception ex) { MainForm.FCurrentGLBatchAction = TGLBatchEnums.GLBatchAction.NONE; //Revert to previous state RevertDataSet(FMainDS, BackupMainDS); TLogging.LogException(ex, Utilities.GetMethodSignature()); throw; } finally { this.Cursor = Cursors.Default; } UpdateRecordNumberDisplay(); return(DeletionSuccessful); }
/// <summary> /// Calculate the base amount for the transactions, and update the totals for the journals and the current batch /// </summary> /// <param name="AMainDS"></param> /// <param name="ACurrentBatchRow"></param> /// <param name="ACurrentJournalNumber"></param> /// <returns>false if no change to batch totals</returns> public static bool UpdateRecurringBatchTotals(ref GLBatchTDS AMainDS, ref ARecurringBatchRow ACurrentBatchRow, Int32 ACurrentJournalNumber = 0) { #region Validate Arguments if (AMainDS == null) { throw new EFinanceSystemDataObjectNullOrEmptyException(String.Format(Catalog.GetString( "Function:{0} - The Recurring GL Batch dataset is null!"), Utilities.GetMethodName(true))); } else if (ACurrentBatchRow == null) { throw new EFinanceSystemDataObjectNullOrEmptyException(String.Format(Catalog.GetString( "Function:{0} - The Recurring GL Batch data row is null!"), Utilities.GetMethodName(true))); } #endregion Validate Arguments bool AmountsUpdated = false; decimal BatchDebitTotal = 0.0m; decimal BatchCreditTotal = 0.0m; DataView JournalDV = new DataView(AMainDS.ARecurringJournal); JournalDV.RowFilter = String.Format("{0}={1}", ARecurringJournalTable.GetBatchNumberDBName(), ACurrentBatchRow.BatchNumber); foreach (DataRowView journalView in JournalDV) { GLBatchTDSARecurringJournalRow journalRow = (GLBatchTDSARecurringJournalRow)journalView.Row; if (((ACurrentJournalNumber > 0) && (ACurrentJournalNumber == journalRow.JournalNumber)) || (ACurrentJournalNumber == 0)) { if ((UpdateRecurringJournalTotals(ref AMainDS, ref journalRow))) { AmountsUpdated = true; } } BatchDebitTotal += journalRow.JournalDebitTotal; BatchCreditTotal += journalRow.JournalCreditTotal; } if ((ACurrentBatchRow.BatchDebitTotal != BatchDebitTotal) || (ACurrentBatchRow.BatchCreditTotal != BatchCreditTotal)) { ACurrentBatchRow.BatchDebitTotal = BatchDebitTotal; ACurrentBatchRow.BatchCreditTotal = BatchCreditTotal; AmountsUpdated = true; } return AmountsUpdated; }
/// <summary> /// update the journal header fields from a batch /// </summary> /// <param name="ABatch"></param> public void UpdateHeaderTotals(ARecurringBatchRow ABatch) { decimal sumDebits = 0.0M; decimal sumCredits = 0.0M; DataView JournalDV = new DataView(FMainDS.ARecurringJournal); JournalDV.RowFilter = String.Format("{0}={1}", ARecurringJournalTable.GetBatchNumberDBName(), ABatch.BatchNumber); foreach (DataRowView v in JournalDV) { ARecurringJournalRow r = (ARecurringJournalRow)v.Row; sumCredits += r.JournalCreditTotal; sumDebits += r.JournalDebitTotal; } FPetraUtilsObject.DisableDataChangedEvent(); txtCurrentPeriod.Text = ABatch.BatchPeriod.ToString(); txtDebit.NumberValueDecimal = sumDebits; ABatch.BatchDebitTotal = sumDebits; txtCredit.NumberValueDecimal = sumCredits; ABatch.BatchCreditTotal = sumCredits; txtControl.NumberValueDecimal = ABatch.BatchControlTotal; FPetraUtilsObject.EnableDataChangedEvent(); }
/// <summary> /// load the transactions into the grid /// </summary> /// <param name="ALedgerNumber"></param> /// <param name="ABatchNumber"></param> /// <param name="AJournalNumber"></param> /// <param name="ACurrencyCode"></param> /// <param name="AFromBatchTab"></param> /// <returns>True if new GL transactions were loaded, false if transactions had been loaded already.</returns> public bool LoadTransactions(Int32 ALedgerNumber, Int32 ABatchNumber, Int32 AJournalNumber, string ACurrencyCode, bool AFromBatchTab = false) { TFrmStatusDialog dlgStatus = null; bool DifferentBatchSelected = false; FLoadCompleted = false; FBatchRow = GetBatchRow(); FJournalRow = GetJournalRow(); //FBatchNumber and FJournalNumber may have already been set outside // so need to reset to previous value if (txtBatchNumber.Text.Length > 0) { FBatchNumber = Int32.Parse(txtBatchNumber.Text); } if (txtJournalNumber.Text.Length > 0) { FJournalNumber = Int32.Parse(txtJournalNumber.Text); } if (FLedgerNumber == -1) { InitialiseControls(); } try { this.Cursor = Cursors.WaitCursor; //Check if the same batch is selected, so no need to apply filter if ((FLedgerNumber == ALedgerNumber) && (FBatchNumber == ABatchNumber) && (FJournalNumber == AJournalNumber) && (FTransactionCurrency == ACurrencyCode) && (FMainDS.ARecurringTransaction.DefaultView.Count > 0)) { //Same as previously selected //Need to reconnect FPrev in some circumstances if (FPreviouslySelectedDetailRow == null) { DataRowView rowView = (DataRowView)grdDetails.Rows.IndexToDataSourceRow(FPrevRowChangedRow); if (rowView != null) { FPreviouslySelectedDetailRow = (GLBatchTDSARecurringTransactionRow)(rowView.Row); } } if (GetSelectedRowIndex() > 0) { if (AFromBatchTab) { SelectRowInGrid(GetSelectedRowIndex()); } else { GetDetailsFromControls(GetSelectedDetailRow()); } } FLoadCompleted = true; return false; } // Different batch selected DifferentBatchSelected = true; bool requireControlSetup = (FLedgerNumber == -1) || (FTransactionCurrency != ACurrencyCode); //Handle dialog dlgStatus = new TFrmStatusDialog(FPetraUtilsObject.GetForm()); if (FShowStatusDialogOnLoad) { dlgStatus.Show(); FShowStatusDialogOnLoad = false; dlgStatus.Heading = String.Format(Catalog.GetString("Recurring Batch {0}, Journal {1}"), ABatchNumber, AJournalNumber); dlgStatus.CurrentStatus = Catalog.GetString("Loading transactions ..."); } FLedgerNumber = ALedgerNumber; FBatchNumber = ABatchNumber; FJournalNumber = AJournalNumber; FTransactionNumber = -1; FTransactionCurrency = ACurrencyCode; FPreviouslySelectedDetailRow = null; grdDetails.SuspendLayout(); //Empty grids before filling them grdDetails.DataSource = null; grdAnalAttributes.DataSource = null; // This sets the main part of the filter but excluding the additional items set by the user GUI // It gets the right sort order SetTransactionDefaultView(); //Set the Analysis attributes filter as well FAnalysisAttributesLogic = new TAnalysisAttributes(FLedgerNumber, FBatchNumber, FJournalNumber); FAnalysisAttributesLogic.SetRecurringTransAnalAttributeDefaultView(FMainDS); FMainDS.ARecurringTransAnalAttrib.DefaultView.AllowNew = false; //Load from server if necessary if (FMainDS.ARecurringTransaction.DefaultView.Count == 0) { dlgStatus.CurrentStatus = Catalog.GetString("Requesting transactions from server..."); FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadARecurringTransactionARecurringTransAnalAttrib(ALedgerNumber, ABatchNumber, AJournalNumber)); } else if (FMainDS.ARecurringTransAnalAttrib.DefaultView.Count == 0) // just in case transactions have been loaded in a separate process without analysis attributes { dlgStatus.CurrentStatus = Catalog.GetString("Requesting analysis attributes from server..."); FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadARecurringTransAnalAttribForJournal(ALedgerNumber, ABatchNumber, AJournalNumber)); } // We need to call this because we have not called ShowData(), which would have set it. This differs from the Gift screen. grdDetails.DataSource = new DevAge.ComponentModel.BoundDataView(FMainDS.ARecurringTransaction.DefaultView); // Now we set the full filter dlgStatus.CurrentStatus = Catalog.GetString("Selecting the records..."); FFilterAndFindObject.ApplyFilter(); dlgStatus.CurrentStatus = Catalog.GetString("Configuring analysis attributes ..."); if (grdAnalAttributes.Columns.Count == 1) { grdAnalAttributes.SpecialKeys = GridSpecialKeys.Default | GridSpecialKeys.Tab; FcmbAnalAttribValues = new SourceGrid.Cells.Editors.ComboBox(typeof(string)); FcmbAnalAttribValues.EnableEdit = true; FcmbAnalAttribValues.EditableMode = EditableMode.Focus; grdAnalAttributes.AddTextColumn("Value", FMainDS.ARecurringTransAnalAttrib.Columns[ARecurringTransAnalAttribTable.GetAnalysisAttributeValueDBName()], 100, FcmbAnalAttribValues); FcmbAnalAttribValues.Control.SelectedValueChanged += new EventHandler(this.AnalysisAttributeValueChanged); grdAnalAttributes.Columns[0].Width = 99; } grdAnalAttributes.DataSource = new DevAge.ComponentModel.BoundDataView(FMainDS.ARecurringTransAnalAttrib.DefaultView); grdAnalAttributes.SetHeaderTooltip(0, Catalog.GetString("Type")); grdAnalAttributes.SetHeaderTooltip(1, Catalog.GetString("Value")); //Always show active and inactive values if (requireControlSetup) { //Load all analysis attribute values if (FCacheDS == null) { dlgStatus.CurrentStatus = Catalog.GetString("Loading analysis attributes ..."); FCacheDS = TRemote.MFinance.GL.WebConnectors.LoadAAnalysisAttributes(FLedgerNumber, FActiveOnly); } SetupExtraGridFunctionality(); dlgStatus.CurrentStatus = Catalog.GetString("Initialising accounts and cost centres ..."); // We suppress change detection because these are the correct values // Then initialise our combo boxes for the correct account codes and cost centres bool prevSuppressChangeDetection = FPetraUtilsObject.SuppressChangeDetection; FPetraUtilsObject.SuppressChangeDetection = true; TFinanceControls.InitialiseAccountList(ref cmbDetailAccountCode, FLedgerNumber, true, false, FActiveOnly, false, ACurrencyCode, true); TFinanceControls.InitialiseCostCentreList(ref cmbDetailCostCentreCode, FLedgerNumber, true, false, FActiveOnly, false); FPetraUtilsObject.SuppressChangeDetection = prevSuppressChangeDetection; cmbDetailAccountCode.AttachedLabel.Text = TFinanceControls.SELECT_VALID_ACCOUNT; cmbDetailCostCentreCode.AttachedLabel.Text = TFinanceControls.SELECT_VALID_COST_CENTRE; } //Old data may not have correct LastTransactionNumber if (FJournalRow.LastTransactionNumber != FMainDS.ARecurringTransaction.DefaultView.Count) { if (GLRoutines.UpdateRecurringJournalLastTransaction(ref FMainDS, ref FJournalRow)) { FPetraUtilsObject.SetChangedFlag(); } } //Check for incorrect Exchange rate to base (mainly for existing Petra data) foreach (DataRowView drv in FMainDS.ARecurringTransaction.DefaultView) { ARecurringTransactionRow rtr = (ARecurringTransactionRow)drv.Row; if (rtr.ExchangeRateToBase == 0) { rtr.ExchangeRateToBase = 1; FPetraUtilsObject.HasChanges = true; } } UpdateTransactionTotals(); grdDetails.ResumeLayout(); FLoadCompleted = true; ShowData(); SelectRowInGrid(1); ShowDetails(); //Needed because of how currency is handled UpdateChangeableStatus(); UpdateRecordNumberDisplay(); FFilterAndFindObject.SetRecordNumberDisplayProperties(); //Check for missing analysis attributes and their values if (grdDetails.Rows.Count > 1) { string updatedTransactions = string.Empty; dlgStatus.CurrentStatus = Catalog.GetString("Checking analysis attributes ..."); FAnalysisAttributesLogic.ReconcileRecurringTransAnalysisAttributes(FMainDS, out updatedTransactions); if (updatedTransactions.Length > 0) { //Remove trailing comma updatedTransactions = updatedTransactions.Remove(updatedTransactions.Length - 2); MessageBox.Show(String.Format(Catalog.GetString( "Analysis Attributes have been updated in transaction(s): {0}.{1}{1}Remember to check their values."), updatedTransactions, Environment.NewLine), "Analysis Attributes", MessageBoxButtons.OK, MessageBoxIcon.Information); FPetraUtilsObject.SetChangedFlag(); } } RefreshAnalysisAttributesGrid(); } catch (Exception ex) { TLogging.Log(String.Format("Method:{0} - Unexpected error!{1}{1}{2}", Utilities.GetMethodSignature(), Environment.NewLine, ex.Message)); throw ex; } finally { if (dlgStatus != null) { dlgStatus.Close(); } this.Cursor = Cursors.Default; } return DifferentBatchSelected; }
private static bool ValidateRecurringGLJournalTransactionNumbering(ref GLBatchTDS AGLBatch, ref ARecurringBatchRow ARecurringBatchToSubmit, ref TVerificationResultCollection AVerifications) { #region Validate Arguments if (AGLBatch.ARecurringJournal == null) { throw new EFinanceSystemDataTableReturnedNoDataException(String.Format(Catalog.GetString( "Function:{0} - No Recurring GL Journal data is present!"), Utilities.GetMethodName(true))); } #endregion Validate Arguments //Default to most likely outcome bool NumberingIsValid = true; string SQLStatement = string.Empty; string TempTableName = "TempCheckForConsecutiveRecurringTransactions"; //Parameters for SQL as strings string prmLedgerNumber = ARecurringBatchToSubmit.LedgerNumber.ToString(); string prmBatchNumber = ARecurringBatchToSubmit.BatchNumber.ToString(); //Tables with alias string JournalTableAlias = "j"; string jJournalTable = ARecurringJournalTable.GetTableDBName() + " " + JournalTableAlias; string TransactionTableAlias = "t"; string tTransactionTable = ARecurringTransactionTable.GetTableDBName() + " " + TransactionTableAlias; //Fields and Aliases string jLedgerNumber = JournalTableAlias + "." + ARecurringJournalTable.GetLedgerNumberDBName(); string jBatchNumber = JournalTableAlias + "." + ARecurringJournalTable.GetBatchNumberDBName(); string jBatchNumberAlias = "BatchNumber"; string jJournalNumber = JournalTableAlias + "." + ARecurringJournalTable.GetJournalNumberDBName(); string jJournalNumberAlias = "JournalNumber"; string jJournalLastTransaction = JournalTableAlias + "." + ARecurringJournalTable.GetLastTransactionNumberDBName(); string jJournalLastTransactionAlias = "JournalLastTransaction"; string tLedgerNumber = TransactionTableAlias + "." + ARecurringTransactionTable.GetLedgerNumberDBName(); string tBatchNumber = TransactionTableAlias + "." + ARecurringTransactionTable.GetBatchNumberDBName(); string tJournalNumber = TransactionTableAlias + "." + ARecurringTransactionTable.GetJournalNumberDBName(); string tTransactionNumber = TransactionTableAlias + "." + ARecurringTransactionTable.GetTransactionNumberDBName(); string tFirstTransactionAlias = "FirstTransaction"; string tLastTransactionAlias = "LastTransaction"; string tCountTransactionAlias = "CountTransaction"; try { DataTable tempTable = AGLBatch.Tables.Add(TempTableName); tempTable.Columns.Add(jBatchNumberAlias, typeof(Int32)); tempTable.Columns.Add(jJournalNumberAlias, typeof(Int32)); tempTable.Columns.Add(jJournalLastTransactionAlias, typeof(Int32)); tempTable.Columns.Add(tFirstTransactionAlias, typeof(Int32)); tempTable.Columns.Add(tLastTransactionAlias, typeof(Int32)); tempTable.Columns.Add(tCountTransactionAlias, typeof(Int32)); SQLStatement = "SELECT " + jBatchNumber + " " + jBatchNumberAlias + ", " + jJournalNumber + " " + jJournalNumberAlias + "," + " MIN(" + jJournalLastTransaction + ") " + jJournalLastTransactionAlias + "," + " COALESCE(MIN(" + tTransactionNumber + "), 0) " + tFirstTransactionAlias + "," + " COALESCE(MAX(" + tTransactionNumber + "), 0) " + tLastTransactionAlias + "," + " Count(" + tTransactionNumber + ") " + tCountTransactionAlias + " FROM " + jJournalTable + " LEFT OUTER JOIN " + tTransactionTable + " ON " + jLedgerNumber + " = " + tLedgerNumber + " AND " + jBatchNumber + " = " + tBatchNumber + " AND " + jJournalNumber + " = " + tJournalNumber + " WHERE " + jLedgerNumber + " = " + prmLedgerNumber + " AND " + jBatchNumber + " = " + prmBatchNumber + " GROUP BY " + jBatchNumber + ", " + jJournalNumber + ";"; GLBatchTDS GLBatch = AGLBatch; TDBTransaction transaction = null; DBAccess.GDBAccessObj.GetNewOrExistingAutoReadTransaction(IsolationLevel.ReadCommitted, TEnforceIsolationLevel.eilMinimum, ref transaction, delegate { DBAccess.GDBAccessObj.Select(GLBatch, SQLStatement, TempTableName, transaction); }); //As long as Batches exist, rows will be returned int numTempRows = AGLBatch.Tables[TempTableName].Rows.Count; DataView tempDV = new DataView(AGLBatch.Tables[TempTableName]); //Confirm are all equal and correct - the most common tempDV.RowFilter = string.Format("{0}={1} And {1}={2} And {0}={2} And (({2}>0 And {3}=1) Or ({2}=0 And {3}=0))", jJournalLastTransactionAlias, tLastTransactionAlias, tCountTransactionAlias, tFirstTransactionAlias); //If all records are correct, nothing to do if (tempDV.Count == numTempRows) { return NumberingIsValid; } //!!Reaching this point means there are issues that need addressing. //Confirm that no negative numbers exist tempDV.RowFilter = string.Format("{0} < 0 Or {1} < 0", jJournalLastTransactionAlias, tFirstTransactionAlias); if (tempDV.Count > 0) { string errMessage = "The following Recurring Journals have a negative LastTransactionNumber or have Transactions with a negative TransactionNumber!"; foreach (DataRowView drv in tempDV) { errMessage += string.Format("{0}Batch:{1} Journal:{2}", Environment.NewLine, drv[jBatchNumberAlias], drv[jJournalNumberAlias]); } AVerifications.Add(new TVerificationResult( String.Format(Catalog.GetString("Cannot submit Recurring Batch {0} in Ledger {1}"), ARecurringBatchToSubmit.BatchNumber, ARecurringBatchToSubmit.LedgerNumber), errMessage, TResultSeverity.Resv_Critical)); return false; } //Display non-sequential transactions tempDV.RowFilter = string.Format("{2}>0 And ({3}<>1 Or {1}<>{2})", jJournalLastTransactionAlias, tLastTransactionAlias, tCountTransactionAlias, tFirstTransactionAlias); if (tempDV.Count > 0) { string errMessage = "The following Recurring Journals have gaps in their Transaction numbering! You will need to cancel the Journal(s) and recreate:"; foreach (DataRowView drv in tempDV) { errMessage += string.Format("{0}Batch:{1} Journal:{2}", Environment.NewLine, drv[jBatchNumberAlias], drv[jJournalNumberAlias]); } AVerifications.Add(new TVerificationResult( String.Format(Catalog.GetString("Cannot submit Recurring Batch {0} in Ledger {1}"), ARecurringBatchToSubmit.BatchNumber, ARecurringBatchToSubmit.LedgerNumber), errMessage, TResultSeverity.Resv_Critical)); return false; } //The next most likely, is where the JournalLastTransaction needs updating //Display mismatched journal last number tempDV.RowFilter = string.Format("{0}<>{1} And {1}={2} And (({2}>0 And {3}=1) Or ({2}=0 And {3}=0))", jJournalLastTransactionAlias, tLastTransactionAlias, tCountTransactionAlias, tFirstTransactionAlias); DataView journalsDV = new DataView(AGLBatch.ARecurringJournal); if (tempDV.Count > 0) { //This means the LastTransactionNumber field needs to be updated and is incorrect foreach (DataRowView drv in tempDV) { journalsDV.RowFilter = String.Format("{0}={1} And {2}={3}", ARecurringJournalTable.GetBatchNumberDBName(), drv[jBatchNumberAlias], ARecurringJournalTable.GetJournalNumberDBName(), drv[jJournalNumberAlias]); foreach (DataRowView journals in journalsDV) { ARecurringJournalRow journalRow = (ARecurringJournalRow)journals.Row; journalRow.LastTransactionNumber = Convert.ToInt32(drv[tLastTransactionAlias]); } } } } catch (Exception ex) { TLogging.Log(String.Format("Method:{0} - Unexpected error!{1}{1}{2}", Utilities.GetMethodSignature(), Environment.NewLine, ex.Message)); throw ex; } finally { if (AGLBatch.Tables.Contains(TempTableName)) { AGLBatch.Tables.Remove(TempTableName); } } return NumberingIsValid; }
/// <summary> /// Validates the recurring GL Detail data. /// </summary> /// <param name="AContext">Context that describes where the data validation failed.</param> /// <param name="ABatchRow">Manually added to bring over some GL Batch fields</param> /// <param name="ARow">The <see cref="DataRow" /> which holds the the data against which the validation is run.</param> /// <param name="AVerificationResultCollection">Will be filled with any <see cref="TVerificationResult" /> items if /// data validation errors occur.</param> /// <returns>True if the validation found no data validation errors, otherwise false.</returns> public static bool ValidateRecurringGLDetailManual(object AContext, ARecurringBatchRow ABatchRow, ARecurringTransactionRow ARow, ref TVerificationResultCollection AVerificationResultCollection) { DataColumn ValidationColumn; TVerificationResult VerificationResult = null; object ValidationContext; int VerifResultCollAddedCount = 0; // Don't validate deleted DataRows if (ARow.RowState == DataRowState.Deleted) { return(true); } //TransactionAmount is not in the dictionary so had to pass the control directly // also needed to handle reference if (true) { // 'GL amount must be non-zero ValidationColumn = ARow.Table.Columns[ARecurringTransactionTable.ColumnTransactionAmountId]; ValidationContext = String.Format("Transaction number {0} (batch:{1} journal:{2})", ARow.TransactionNumber, ARow.BatchNumber, ARow.JournalNumber); VerificationResult = TNumericalChecks.IsPositiveDecimal(ARow.TransactionAmount, "Amount of " + ValidationContext, AContext, ValidationColumn); if (VerificationResult != null) { VerificationResult.SuppressValidationToolTip = true; } // Handle addition/removal to/from TVerificationResultCollection if (AVerificationResultCollection.Auto_Add_Or_AddOrRemove(AContext, VerificationResult)) { VerifResultCollAddedCount++; } return(VerifResultCollAddedCount == 0); } // Narrative must not be empty ValidationColumn = ARow.Table.Columns[ARecurringTransactionTable.ColumnNarrativeId]; ValidationContext = String.Format("Transaction number {0} (batch:{1} journal:{2})", ARow.TransactionNumber, ARow.BatchNumber, ARow.JournalNumber); if (true) { VerificationResult = TStringChecks.StringMustNotBeEmpty(ARow.Narrative, "Narrative of " + ValidationContext, AContext, ValidationColumn); // Handle addition/removal to/from TVerificationResultCollection if (AVerificationResultCollection.Auto_Add_Or_AddOrRemove(AContext, VerificationResult)) { VerifResultCollAddedCount++; } } if (true) { ValidationColumn = ARow.Table.Columns[ARecurringTransactionTable.ColumnReferenceId]; ValidationContext = String.Format("Transaction number {0} (batch:{1} journal:{2})", ARow.TransactionNumber, ARow.BatchNumber, ARow.JournalNumber); if (true) { VerificationResult = TStringChecks.StringMustNotBeEmpty(ARow.Reference, "Reference of " + ValidationContext, AContext, ValidationColumn); // Handle addition/removal to/from TVerificationResultCollection if (AVerificationResultCollection.Auto_Add_Or_AddOrRemove(AContext, VerificationResult)) { VerifResultCollAddedCount++; } } } return(VerifResultCollAddedCount == 0); }
/// <summary> /// Deletes the current row and optionally populates a completion message /// </summary> /// <param name="ARowToDelete">the currently selected row to delete</param> /// <param name="ACompletionMessage">if specified, is the deletion completion message</param> /// <returns>true if row deletion is successful</returns> private bool DeleteRowManual(ARecurringBatchRow ARowToDelete, ref string ACompletionMessage) { //Assign default value(s) bool DeletionSuccessful = false; if (ARowToDelete == null) { return(DeletionSuccessful); } int BatchNumber = ARowToDelete.BatchNumber; //Backup the Dataset for reversion purposes GLBatchTDS BackupMainDS = (GLBatchTDS)FMainDS.Copy(); BackupMainDS.Merge(FMainDS); if (ARowToDelete.RowState != DataRowState.Added) { //Reject any changes which may fail validation ARowToDelete.RejectChanges(); ShowDetails(ARowToDelete); } try { this.Cursor = Cursors.WaitCursor; ACompletionMessage = String.Format(Catalog.GetString("Batch no.: {0} deleted successfully."), BatchNumber); // Delete the associated recurring transaction analysis attributes DataView viewRecurringTransAnalAttrib = new DataView(FMainDS.ARecurringTransAnalAttrib); viewRecurringTransAnalAttrib.RowFilter = String.Format("{0}={1} AND {2}={3}", ARecurringTransAnalAttribTable.GetLedgerNumberDBName(), FLedgerNumber, ARecurringTransAnalAttribTable.GetBatchNumberDBName(), BatchNumber); foreach (DataRowView row in viewRecurringTransAnalAttrib) { row.Delete(); } // Delete the associated recurring transactions DataView viewRecurringTransaction = new DataView(FMainDS.ARecurringTransaction); viewRecurringTransaction.RowFilter = String.Format("{0}={1} AND {2}={3}", ARecurringTransactionTable.GetLedgerNumberDBName(), FLedgerNumber, ARecurringTransactionTable.GetBatchNumberDBName(), BatchNumber); foreach (DataRowView row in viewRecurringTransaction) { row.Delete(); } // Delete the associated recurring journals DataView viewRecurringJournal = new DataView(FMainDS.ARecurringJournal); viewRecurringJournal.RowFilter = String.Format("{0}={1} AND {2}={3}", ARecurringJournalTable.GetLedgerNumberDBName(), FLedgerNumber, ARecurringJournalTable.GetBatchNumberDBName(), BatchNumber); foreach (DataRowView row in viewRecurringJournal) { row.Delete(); } // Delete the recurring batch row. ARowToDelete.Delete(); DeletionSuccessful = true; } catch (Exception ex) { ACompletionMessage = ex.Message; MessageBox.Show(ACompletionMessage, "Deletion Error", MessageBoxButtons.OK, MessageBoxIcon.Error); //Revert to previous state FMainDS.Merge(BackupMainDS); } finally { this.Cursor = Cursors.Default; } UpdateRecordNumberDisplay(); return(DeletionSuccessful); }