/// <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;
        }
        /// <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;
        }