/// <summary>
        /// Posts a batch
        /// </summary>
        /// <param name="ACurrentBatchRow">The data row corresponding to the batch to post</param>
        /// <param name="AEffectiveDate">The effective date for the batch</param>
        /// <param name="AStartDateCurrentPeriod">The earliest postable date</param>
        /// <param name="AEndDateLastForwardingPeriod">The latest postable date</param>
        /// <returns>True if the batch was successfully posted</returns>
        public bool PostBatch(ABatchRow ACurrentBatchRow,
                              DateTime AEffectiveDate,
                              DateTime AStartDateCurrentPeriod,
                              DateTime AEndDateLastForwardingPeriod)
        {
            bool RetVal = false;

            if (!SaveBatchForPosting())
            {
                return(RetVal);
            }

            // TODO: display progress of posting
            TVerificationResultCollection Verifications;

            int CurrentBatchNumber = ACurrentBatchRow.BatchNumber;

            if ((AEffectiveDate.Date < AStartDateCurrentPeriod) || (AEffectiveDate.Date > AEndDateLastForwardingPeriod))
            {
                MessageBox.Show(String.Format(Catalog.GetString(
                                                  "The Date Effective is outside the periods available for posting. Enter a date between {0:d} and {1:d}."),
                                              AStartDateCurrentPeriod,
                                              AEndDateLastForwardingPeriod));

                return(RetVal);
            }

            if (MessageBox.Show(String.Format(Catalog.GetString("Are you sure you want to post batch {0}?"),
                                              CurrentBatchNumber),
                                Catalog.GetString("Question"),
                                MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == System.Windows.Forms.DialogResult.Yes)
            {
                try
                {
                    Cursor.Current = Cursors.WaitCursor;

                    if (!TRemote.MFinance.GL.WebConnectors.PostGLBatch(FLedgerNumber, CurrentBatchNumber, out Verifications))
                    {
                        string ErrorMessages = String.Empty;

                        foreach (TVerificationResult verif in Verifications)
                        {
                            ErrorMessages += "[" + verif.ResultContext + "] " +
                                             verif.ResultTextCaption + ": " +
                                             verif.ResultText + Environment.NewLine;
                        }

                        System.Windows.Forms.MessageBox.Show(ErrorMessages, Catalog.GetString("Posting failed"),
                                                             MessageBoxButtons.OK,
                                                             MessageBoxIcon.Error);
                    }
                    else
                    {
//                                                                                          I don't need to call this directly, because the server calls it:
//                        TFrmGLBatch.PrintPostingRegister(FLedgerNumber, CurrentBatchNumber);

                        // TODO: print reports on successfully posted batch
                        MessageBox.Show(Catalog.GetString("The batch has been posted successfully!"),
                                        Catalog.GetString("Success"),
                                        MessageBoxButtons.OK,
                                        MessageBoxIcon.Information);

                        // refresh the grid, to reflect that the batch has been posted
                        FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadABatchAndContent(FLedgerNumber, CurrentBatchNumber));

                        // make sure that the current dataset is clean,
                        // otherwise the next save would try to modify the posted batch, even though no values have been changed
                        FMainDS.AcceptChanges();

                        // Ensure these tabs will ask the server for updates
                        FMyForm.GetJournalsControl().ClearCurrentSelection();
                        FMyForm.GetTransactionsControl().ClearCurrentSelection();

                        FMyUserControl.UpdateDisplay();

                        RetVal = true;
                    }
                }
                finally
                {
                    Cursor.Current = Cursors.Default;
                }
            }

            return(RetVal);
        }
        /// <summary>
        /// Posts a batch
        /// </summary>
        /// <param name="ACurrentBatchRow">The data row corresponding to the batch to post</param>
        /// <param name="AEffectiveDate">The effective date for the batch</param>
        /// <param name="AStartDateCurrentPeriod">The earliest postable date</param>
        /// <param name="AEndDateLastForwardingPeriod">The latest postable date</param>
        /// <param name="AInactiveValuesWarningOnGLPosting">Warn of inactive values</param>
        /// <returns>
        /// True if the batch was successfully posted
        /// </returns>
        public bool PostBatch(ABatchRow ACurrentBatchRow,
                              DateTime AEffectiveDate,
                              DateTime AStartDateCurrentPeriod,
                              DateTime AEndDateLastForwardingPeriod,
                              bool AInactiveValuesWarningOnGLPosting = true)
        {
            bool RetVal = false;

            if (!SaveBatchForPosting())
            {
                return(RetVal);
            }

            //Load all Batch data
            FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadABatchAndContent(FLedgerNumber, ACurrentBatchRow.BatchNumber));

            if (FCacheDS == null)
            {
                FCacheDS = TRemote.MFinance.GL.WebConnectors.LoadAAnalysisAttributes(FLedgerNumber, false);
            }

            if (FAccountTable == null)
            {
                SetAccountCostCentreTableVariables();
            }

            //Check for inactive values
            int NumInactiveValues = 0;

            if (AInactiveValuesWarningOnGLPosting && !AllowInactiveFieldValues(ACurrentBatchRow.BatchNumber, out NumInactiveValues))
            {
                return(RetVal);
            }

            bool PostWithInactiveValues = (NumInactiveValues > 0);


            // TODO: display progress of posting
            TVerificationResultCollection Verifications;

            int CurrentBatchNumber = ACurrentBatchRow.BatchNumber;

            if ((AEffectiveDate.Date < AStartDateCurrentPeriod) || (AEffectiveDate.Date > AEndDateLastForwardingPeriod))
            {
                MessageBox.Show(String.Format(Catalog.GetString(
                                                  "The Date Effective is outside the periods available for posting. Enter a date between {0:d} and {1:d}."),
                                              AStartDateCurrentPeriod,
                                              AEndDateLastForwardingPeriod));

                return(RetVal);
            }

            // check that a corportate exchange rate exists
            FMyForm.WarnAboutMissingIntlExchangeRate = true;

            if (FMyForm.GetInternationalCurrencyExchangeRate() == 0)
            {
                return(false);
            }

            if (PostWithInactiveValues ||
                (MessageBox.Show(String.Format(Catalog.GetString("Are you sure you want to post GL batch {0}?"),
                                               CurrentBatchNumber),
                                 Catalog.GetString("Question"),
                                 MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) == System.Windows.Forms.DialogResult.Yes))
            {
                try
                {
                    Cursor.Current = Cursors.WaitCursor;

                    if (!TRemote.MFinance.GL.WebConnectors.PostGLBatch(FLedgerNumber, CurrentBatchNumber, out Verifications))
                    {
                        string ErrorMessages = String.Empty;

                        foreach (TVerificationResult verif in Verifications)
                        {
                            ErrorMessages += "[" + verif.ResultContext + "] " +
                                             verif.ResultTextCaption + ": " +
                                             verif.ResultText + Environment.NewLine;
                        }

                        System.Windows.Forms.MessageBox.Show(ErrorMessages, Catalog.GetString("Posting failed"),
                                                             MessageBoxButtons.OK,
                                                             MessageBoxIcon.Error);
                    }
                    else
                    {
                        //I don't need to call this directly, because the server calls it:
                        //TFrmGLBatch.PrintPostingRegister(FLedgerNumber, CurrentBatchNumber);

                        // TODO: print reports on successfully posted batch
                        MessageBox.Show(Catalog.GetString("The batch has been posted successfully!"),
                                        Catalog.GetString("Success"),
                                        MessageBoxButtons.OK,
                                        MessageBoxIcon.Information);

                        // refresh the grid, to reflect that the batch has been posted
                        FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadABatchAndContent(FLedgerNumber, CurrentBatchNumber));

                        // make sure that the current dataset is clean,
                        // otherwise the next save would try to modify the posted batch, even though no values have been changed
                        FMainDS.AcceptChanges();

                        // Ensure these tabs will ask the server for updates
                        FMyForm.GetJournalsControl().ClearCurrentSelection();
                        FMyForm.GetTransactionsControl().ClearCurrentSelection();

                        FMyUserControl.UpdateDisplay();

                        RetVal = true;
                    }
                }
                catch (Exception ex)
                {
                    string msg = (String.Format(Catalog.GetString("Unexpected error occurred during the posting of GL Batch {0}!{1}{1}{2}{1}{1}{3}"),
                                                CurrentBatchNumber,
                                                Environment.NewLine,
                                                ex.Message,
                                                ex.InnerException != null?ex.InnerException.Message:String.Empty));

                    TLogging.LogException(ex, Utilities.GetMethodSignature());
                    MessageBox.Show(msg, "Post GL Batch Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                finally
                {
                    Cursor.Current = Cursors.Default;
                }
            }

            return(RetVal);
        }
        /// <summary>
        /// Reverses the specified batch
        /// </summary>
        /// <param name="ACurrentBatchRow">The DataRow for the batch to be reversed</param>
        /// <param name="ADateForReverseBatch">The reversal date - this will get checked to ensure the date is valid</param>
        /// <param name="AStartDateCurrentPeriod">The earliest date that can be used as reversal date</param>
        /// <param name="AEndDateLastForwardingPeriod">The latest date that can be used as a reversal date</param>
        /// <returns></returns>
        public bool ReverseBatch(ABatchRow ACurrentBatchRow,
                                 DateTime ADateForReverseBatch,
                                 DateTime AStartDateCurrentPeriod,
                                 DateTime AEndDateLastForwardingPeriod)
        {
            //TODO: Allow the user in a dialog to specify the reverse date

            TVerificationResultCollection Verifications;

            if (FPetraUtilsObject.HasChanges)
            {
                // save first, then post
                if (!FMyForm.SaveChanges())
                {
                    // saving failed, therefore do not try to reverse
                    MessageBox.Show(Catalog.GetString("The batch was not reversed due to problems during saving; ") + Environment.NewLine +
                                    Catalog.GetString("Please first save the batch, and then you can reverse it!"),
                                    Catalog.GetString("Failure"), MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return(false);
                }
            }

            try
            {
                FMyForm.Cursor = Cursors.WaitCursor;

                int    SelectedBatchNumber = ACurrentBatchRow.BatchNumber;
                string Msg = string.Empty;

                // load journals belonging to batch
                GLBatchTDS TempDS = TRemote.MFinance.GL.WebConnectors.LoadAJournalAndContent(FLedgerNumber, ACurrentBatchRow.BatchNumber);
                FMainDS.Merge(TempDS);

                foreach (AJournalRow Journal in TempDS.AJournal.Rows)
                {
                    // if at least one journal in the batch has already been reversed then confirm with user
                    if (Journal.Reversed)
                    {
                        Msg = String.Format(Catalog.GetString("One or more of the Journals in Batch {0} have already been reversed. " +
                                                              "Are you sure you want to continue?"),
                                            SelectedBatchNumber);
                        break;
                    }
                }

                if (Msg == string.Empty)
                {
                    Msg = String.Format(Catalog.GetString("Are you sure you want to reverse Batch {0}?"),
                                        SelectedBatchNumber);
                }

                if (MessageBox.Show(Msg, Catalog.GetString("GL Batch Reversal"),
                                    MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
                {
                    TFrmBatchDateDialog Form = new TFrmBatchDateDialog(FMyForm);
                    Form.SetParameters(AStartDateCurrentPeriod, AEndDateLastForwardingPeriod, SelectedBatchNumber);

                    if (Form.ShowDialog() == DialogResult.Cancel)
                    {
                        return(false);
                    }

                    ADateForReverseBatch = Form.BatchDate;

                    int ReversalGLBatch;

                    if (!TRemote.MFinance.GL.WebConnectors.ReverseBatch(FLedgerNumber, SelectedBatchNumber,
                                                                        ADateForReverseBatch,
                                                                        out ReversalGLBatch,
                                                                        out Verifications,
                                                                        false))
                    {
                        string ErrorMessages = String.Empty;

                        foreach (TVerificationResult verif in Verifications)
                        {
                            ErrorMessages += "[" + verif.ResultContext + "] " +
                                             verif.ResultTextCaption + ": " +
                                             verif.ResultText + Environment.NewLine;
                        }

                        System.Windows.Forms.MessageBox.Show(ErrorMessages, Catalog.GetString("Reversal failed"),
                                                             MessageBoxButtons.OK,
                                                             MessageBoxIcon.Error);
                    }
                    else
                    {
                        MessageBox.Show(
                            String.Format(Catalog.GetString("A reversal batch has been created, with batch number {0}!"), ReversalGLBatch),
                            Catalog.GetString("Success"),
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Information);

                        // refresh the grid, to reflect that the batch has been reversed
                        FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadABatchAndContent(FLedgerNumber, ReversalGLBatch));

                        // make sure that the current dataset is clean,
                        // otherwise the next save would try to modify the posted batch, even though no values have been changed
                        FMainDS.AcceptChanges();

                        // Ensure these tabs will ask the server for updates
                        FMyForm.GetJournalsControl().ClearCurrentSelection();
                        FMyForm.GetTransactionsControl().ClearCurrentSelection();

                        FMyUserControl.UpdateDisplay();

                        return(true);
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                FMyForm.Cursor = Cursors.Default;
            }

            return(false);
        }
        /// <summary>
        /// Posts a batch
        /// </summary>
        /// <param name="ACurrentBatchRow">The data row corresponding to the batch to post</param>
        /// <param name="AEffectiveDate">The effective date for the batch</param>
        /// <param name="AStartDateCurrentPeriod">The earliest postable date</param>
        /// <param name="AEndDateLastForwardingPeriod">The latest postable date</param>
        /// <returns>
        /// True if the batch was successfully posted
        /// </returns>
        public bool PostBatch(ABatchRow ACurrentBatchRow,
                              DateTime AEffectiveDate,
                              DateTime AStartDateCurrentPeriod,
                              DateTime AEndDateLastForwardingPeriod)
        {
            if ((ACurrentBatchRow == null) || (ACurrentBatchRow.BatchStatus != MFinanceConstants.BATCH_UNPOSTED))
            {
                return(false);
            }

            int CurrentBatchNumber = ACurrentBatchRow.BatchNumber;

            //Make sure that all control data is in dataset
            FMyForm.GetLatestControlData();

            if (FPetraUtilsObject.HasChanges)
            {
                //Keep this conditional check separate so that it only gets called when necessary
                // and doesn't result in the executon of the next else if which calls same method
                if (!FMyForm.SaveChangesManual(FMyForm.FCurrentGLBatchAction))
                {
                    return(false);
                }
            }
            //This has to be called here as if there are no changes then the DataSavingValidating method
            // which calls the method below, will not run.
            else if (!FMyForm.GetTransactionsControl().AllowInactiveFieldValues(FLedgerNumber,
                                                                                CurrentBatchNumber, FMyForm.FCurrentGLBatchAction))
            {
                return(false);
            }

            //Load all Batch data
            FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadABatchAndRelatedTables(FLedgerNumber, CurrentBatchNumber));

            if (FCacheDS == null)
            {
                FCacheDS = TRemote.MFinance.GL.WebConnectors.LoadAAnalysisAttributes(FLedgerNumber, false);
            }

            if (FAccountTable == null)
            {
                SetAccountCostCentreTableVariables();
            }

            if ((AEffectiveDate.Date < AStartDateCurrentPeriod) || (AEffectiveDate.Date > AEndDateLastForwardingPeriod))
            {
                MessageBox.Show(String.Format(Catalog.GetString(
                                                  "The Date Effective is outside the periods available for posting. Enter a date between {0:d} and {1:d}."),
                                              AStartDateCurrentPeriod,
                                              AEndDateLastForwardingPeriod));

                return(false);
            }

            // check that a corportate exchange rate exists
            FMyForm.WarnAboutMissingIntlExchangeRate = true;

            if (FMyForm.GetInternationalCurrencyExchangeRate() == 0)
            {
                return(false);
            }

            if ((MessageBox.Show(String.Format(Catalog.GetString("Are you sure you want to post GL batch {0}?"),
                                               CurrentBatchNumber),
                                 Catalog.GetString("Question"),
                                 MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) != System.Windows.Forms.DialogResult.Yes))
            {
                return(false);
            }

            TVerificationResultCollection Verifications = new TVerificationResultCollection();

            try
            {
                Cursor.Current = Cursors.WaitCursor;

                Thread postingThread = new Thread(() => PostGLBatch(CurrentBatchNumber, out Verifications));
                postingThread.SetApartmentState(ApartmentState.STA);

                using (TProgressDialog dialog = new TProgressDialog(postingThread))
                {
                    dialog.ShowDialog();
                }

                if (TVerificationHelper.ResultsContainErrorCode(Verifications, PetraErrorCodes.ERR_DB_SERIALIZATION_EXCEPTION))
                {
                    TConcurrentServerTransactions.ShowTransactionSerializationExceptionDialog();
                }
                else if (!TVerificationHelper.IsNullOrOnlyNonCritical(Verifications))
                {
                    TFrmExtendedMessageBox extendedMessageBox = new TFrmExtendedMessageBox(FMyForm);

                    StringBuilder errorMessages = new StringBuilder();
                    int           counter       = 0;

                    errorMessages.AppendLine(Catalog.GetString("________________________GL Posting Errors________________________"));
                    errorMessages.AppendLine();

                    foreach (TVerificationResult verif in Verifications)
                    {
                        counter++;
                        errorMessages.AppendLine(counter.ToString("000") + " - " + verif.ResultText);
                        errorMessages.AppendLine();
                    }

                    extendedMessageBox.ShowDialog(errorMessages.ToString(),
                                                  Catalog.GetString("Post Batch Error"),
                                                  string.Empty,
                                                  TFrmExtendedMessageBox.TButtons.embbOK,
                                                  TFrmExtendedMessageBox.TIcon.embiWarning);
                }
                else
                {
                    MessageBox.Show(Catalog.GetString("The batch has been posted successfully!"),
                                    Catalog.GetString("Success"),
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Information);
                }

                // refresh the grid, to reflect that the batch has been posted (or even maybe had been posted by another user)
                FMainDS.Merge(TRemote.MFinance.GL.WebConnectors.LoadABatchAndRelatedTables(FLedgerNumber, CurrentBatchNumber));

                // make sure that the current dataset is clean,
                // otherwise the next save would try to modify the posted batch, even though no values have been changed
                FMainDS.AcceptChanges();

                // Ensure these tabs will ask the server for updates
                FMyForm.GetTransactionsControl().ClearCurrentSelection();
                FMyForm.GetJournalsControl().ClearCurrentSelection();

                FMyUserControl.UpdateDisplay();
            }
            catch (Exception ex)
            {
                TLogging.LogException(ex, Utilities.GetMethodSignature());
                throw;
            }
            finally
            {
                Cursor.Current = Cursors.Default;
            }

            return(true);
        }