/// <summary>
        /// Method to cancel a specified batch
        /// </summary>
        /// <param name="ABatchRowToCancel"></param>
        /// <returns></returns>
        public bool CancelBatch(AGiftBatchRow ABatchRowToCancel)
        {
            bool CancellationSuccessful = false;

            if ((ABatchRowToCancel == null) || (ABatchRowToCancel.BatchStatus != MFinanceConstants.BATCH_UNPOSTED))
            {
                return(false);
            }

            int  CurrentBatchNo = ABatchRowToCancel.BatchNumber;
            bool CurrentBatchTransactionsLoadedAndCurrent = false;

            string CancelMessage     = string.Empty;
            string CompletionMessage = string.Empty;

            List <string> ModifiedDetailKeys = new List <string>();

            CancelMessage = String.Format(Catalog.GetString("Are you sure you want to cancel Gift Batch {0}?"),
                                          CurrentBatchNo);

            if ((MessageBox.Show(CancelMessage,
                                 "Cancel Gift Batch",
                                 MessageBoxButtons.YesNo,
                                 MessageBoxIcon.Question,
                                 MessageBoxDefaultButton.Button2) != System.Windows.Forms.DialogResult.Yes))
            {
                return(false);
            }

            //Backup the Dataset for reversion purposes
            GiftBatchTDS BackupMainDS = null;

            try
            {
                FMyForm.Cursor = Cursors.WaitCursor;

                //Backup the Dataset for reversion purposes
                BackupMainDS = (GiftBatchTDS)FMainDS.GetChangesTyped(false);

                //Don't run an inactive fields check on this batch
                FMyForm.GetBatchControl().UpdateUnpostedBatchDictionary(CurrentBatchNo);

                //Check if current batch gift details are currently loaded
                CurrentBatchTransactionsLoadedAndCurrent = (FMyForm.GetTransactionsControl().FBatchNumber == CurrentBatchNo);

                //Save and check for inactive values and ex-workers and anonymous gifts
                //  in other unsaved Batches
                FPetraUtilsObject.SetChangedFlag();

                if (!FMyForm.SaveChangesManual(TExtraGiftBatchChecks.GiftBatchAction.CANCELLING, !CurrentBatchTransactionsLoadedAndCurrent))
                {
                    FMyForm.GetBatchControl().UpdateUnpostedBatchDictionary();

                    CompletionMessage = String.Format(Catalog.GetString("Gift Batch {0} has not been cancelled."),
                                                      CurrentBatchNo);

                    MessageBox.Show(CompletionMessage,
                                    "Gift Batch Cancelled",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Information);

                    return(false);
                }

                //Remove any changes to current batch that may cause validation issues
                FMyForm.GetBatchControl().PrepareBatchDataForCancelling(CurrentBatchNo, true);

                if (CurrentBatchTransactionsLoadedAndCurrent)
                {
                    //Clear any transactions currently being edited in the Transaction Tab
                    FMyForm.GetTransactionsControl().ClearCurrentSelection(CurrentBatchNo);
                }

                //Delete transactions
                FMyForm.GetTransactionsControl().DeleteBatchGiftData(CurrentBatchNo, ref ModifiedDetailKeys);

                //Batch is only cancelled and never deleted
                ABatchRowToCancel.BeginEdit();
                ABatchRowToCancel.BatchTotal     = 0;
                ABatchRowToCancel.LastGiftNumber = 0;
                ABatchRowToCancel.BatchStatus    = MFinanceConstants.BATCH_CANCELLED;
                ABatchRowToCancel.EndEdit();

                if (ModifiedDetailKeys.Count > 0)
                {
                    TRemote.MFinance.Gift.WebConnectors.ReversedGiftReset(FLedgerNumber, ModifiedDetailKeys);
                }

                FPetraUtilsObject.SetChangedFlag();
                FMyForm.SaveChangesManual();

                CompletionMessage = String.Format(Catalog.GetString("Batch no.: {0} cancelled successfully."),
                                                  CurrentBatchNo);

                MessageBox.Show(CompletionMessage,
                                "Gift Batch Cancelled",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Information);

                FMyForm.DisableTransactions();

                CancellationSuccessful = true;
            }
            catch (Exception ex)
            {
                //Revert to previous state
                if (BackupMainDS != null)
                {
                    FMainDS.RejectChanges();
                    FMainDS.Merge(BackupMainDS);

                    FMyForm.GetBatchControl().ShowDetailsRefresh();
                }

                TLogging.LogException(ex, Utilities.GetMethodSignature());
                throw;
            }
            finally
            {
                FMyForm.Cursor = Cursors.Default;
            }

            return(CancellationSuccessful);
        }
        /// <summary>
        /// Method to cancel a specified batch
        /// </summary>
        /// <param name="ACurrentBatchRow"></param>
        /// <returns></returns>
        public bool CancelBatch(AGiftBatchRow ACurrentBatchRow)
        {
            //Assign default value(s)
            bool CancellationSuccessful = false;

            string CancelMessage     = string.Empty;
            string CompletionMessage = string.Empty;

            List <string> ModifiedDetailKeys = new List <string>();

            if ((ACurrentBatchRow == null) || (ACurrentBatchRow.BatchStatus != MFinanceConstants.BATCH_UNPOSTED))
            {
                return(CancellationSuccessful);
            }

            int CurrentBatchNo = ACurrentBatchRow.BatchNumber;

            CancelMessage = String.Format(Catalog.GetString("Are you sure you want to cancel gift batch number: {0}?"),
                                          ACurrentBatchRow.BatchNumber);

            if ((MessageBox.Show(CancelMessage,
                                 "Cancel Batch",
                                 MessageBoxButtons.YesNo,
                                 MessageBoxIcon.Question,
                                 MessageBoxDefaultButton.Button2) != System.Windows.Forms.DialogResult.Yes))
            {
                return(CancellationSuccessful);
            }

            //Backup the Dataset for reversion purposes
            GiftBatchTDS BackupMainDS = (GiftBatchTDS)FMainDS.Copy();

            BackupMainDS.Merge(FMainDS);

            try
            {
                FMyForm.Cursor = Cursors.WaitCursor;

                //Normally need to set the message parameters before the delete is performed if requiring any of the row values
                CompletionMessage = String.Format(Catalog.GetString("Batch no.: {0} cancelled successfully."),
                                                  ACurrentBatchRow.BatchNumber);

                FMyForm.GetBatchControl().UndoModifiedBatchRow(ACurrentBatchRow, true);

                //Load all journals for current Batch
                //clear any transactions currently being editied in the Transaction Tab
                FMyForm.GetTransactionsControl().ClearCurrentSelection();

                //Delete transactions
                DataView GiftDV       = new DataView(FMainDS.AGift);
                DataView GiftDetailDV = new DataView(FMainDS.AGiftDetail);

                GiftDV.AllowDelete       = true;
                GiftDetailDV.AllowDelete = true;

                GiftDV.RowFilter = String.Format("{0}={1}",
                                                 AGiftTable.GetBatchNumberDBName(),
                                                 CurrentBatchNo);

                GiftDV.Sort = AGiftTable.GetGiftTransactionNumberDBName() + " DESC";

                GiftDetailDV.RowFilter = String.Format("{0}={1}",
                                                       AGiftDetailTable.GetBatchNumberDBName(),
                                                       CurrentBatchNo);

                GiftDetailDV.Sort = String.Format("{0} DESC, {1} DESC",
                                                  AGiftDetailTable.GetGiftTransactionNumberDBName(),
                                                  AGiftDetailTable.GetDetailNumberDBName());

                foreach (DataRowView drv in GiftDetailDV)
                {
                    AGiftDetailRow gdr = (AGiftDetailRow)drv.Row;

                    // if the gift detail being cancelled is a reversed gift
                    if (gdr.ModifiedDetail && !string.IsNullOrEmpty(gdr.ModifiedDetailKey))
                    {
                        ModifiedDetailKeys.Add(gdr.ModifiedDetailKey);
                    }

                    gdr.Delete();
                }

                for (int i = 0; i < GiftDV.Count; i++)
                {
                    GiftDV.Delete(i);
                }

                //Batch is only cancelled and never deleted
                ACurrentBatchRow.BatchTotal     = 0;
                ACurrentBatchRow.LastGiftNumber = 0;
                ACurrentBatchRow.BatchStatus    = MFinanceConstants.BATCH_CANCELLED;

                FPetraUtilsObject.SetChangedFlag();

                // save first
                if (FMyForm.SaveChanges())
                {
                    if (ModifiedDetailKeys.Count > 0)
                    {
                        TRemote.MFinance.Gift.WebConnectors.ReversedGiftReset(FLedgerNumber, ModifiedDetailKeys);
                    }

                    MessageBox.Show(CompletionMessage,
                                    "Batch Cancelled",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Information);
                }
                else
                {
                    throw new Exception(Catalog.GetString("The batch failed to save after being cancelled! Reopen the form and retry."));
                }

                CancellationSuccessful = true;
            }
            catch (Exception ex)
            {
                //Revert to previous state
                FMainDS.Merge(BackupMainDS);

                CompletionMessage = ex.Message;
                MessageBox.Show(CompletionMessage,
                                "Cancellation Error",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Error);

                TLogging.LogException(ex, Utilities.GetMethodSignature());
                throw;
            }
            finally
            {
                FMyForm.Cursor = Cursors.Default;
            }

            return(CancellationSuccessful);
        }
        /// <summary>
        /// Main method to post a specified batch
        /// </summary>
        /// <param name="ACurrentBatchRow">The batch row to post</param>
        /// <param name="ARefreshGUIAfterPosting">Will be set to true if the GUI should be updated.  Can be true even if Posting fails
        /// <param name="AWarnOfInactiveValues">True means user is warned if inactive values exist</param>
        /// <param name="ADonorZeroIsValid"></param>
        /// <param name="ARecipientZeroIsValid"></param>
        /// <param name="APostingAlreadyConfirmed">True means ask user if they want to post</param>
        /// if the server gets a SerializableTransactionException</param>
        /// <returns>True if the batch was successfully posted</returns>
        public bool PostBatch(AGiftBatchRow ACurrentBatchRow,
                              out bool ARefreshGUIAfterPosting,
                              bool AWarnOfInactiveValues    = true,
                              bool ADonorZeroIsValid        = false,
                              bool ARecipientZeroIsValid    = false,
                              bool APostingAlreadyConfirmed = false)
        {
            ARefreshGUIAfterPosting = false;

            if ((ACurrentBatchRow == null) || (ACurrentBatchRow.BatchStatus != MFinanceConstants.BATCH_UNPOSTED))
            {
                return(false);
            }

            FSelectedBatchNumber = ACurrentBatchRow.BatchNumber;

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

            //Copy all batch data to new table
            GiftBatchTDSAGiftDetailTable BatchGiftDetails = new GiftBatchTDSAGiftDetailTable();
            DataView BatchGiftDetailsDV = new DataView(FMainDS.AGiftDetail);

            BatchGiftDetailsDV.RowFilter = string.Format("{0}={1}",
                                                         AGiftDetailTable.GetBatchNumberDBName(),
                                                         FSelectedBatchNumber);

            BatchGiftDetailsDV.Sort = string.Format("{0} ASC, {1} ASC, {2} ASC",
                                                    AGiftDetailTable.GetBatchNumberDBName(),
                                                    AGiftDetailTable.GetGiftTransactionNumberDBName(),
                                                    AGiftDetailTable.GetDetailNumberDBName());

            foreach (DataRowView drv in BatchGiftDetailsDV)
            {
                GiftBatchTDSAGiftDetailRow gBRow = (GiftBatchTDSAGiftDetailRow)drv.Row;
                BatchGiftDetails.Rows.Add((object[])gBRow.ItemArray.Clone());
            }

            //Save and check for inactive values and ex-workers and anonymous gifts
            if (FPetraUtilsObject.HasChanges)
            {
                //Keep this conditional check separate from the one above so that it only gets called
                // when necessary and doesn't result in the executon of the same method
                if (!FMyForm.SaveChangesForPosting(BatchGiftDetails))
                {
                    return(false);
                }
                else
                {
                    APostingAlreadyConfirmed = true;
                }
            }
            else
            {
                //This has to be called here because if there are no changes then the DataSavingValidating
                // method which calls the method below, will not run.
                if (!FMyForm.GetBatchControl().AllowInactiveFieldValues(ref APostingAlreadyConfirmed,
                                                                        TExtraGiftBatchChecks.GiftBatchAction.POSTING) ||
                    FMyForm.GiftHasExWorkerOrAnon(BatchGiftDetails)
                    )
                {
                    return(false);
                }
            }

            //Check hash total validity
            if ((ACurrentBatchRow.HashTotal != 0) &&
                (ACurrentBatchRow.BatchTotal != ACurrentBatchRow.HashTotal))
            {
                MessageBox.Show(String.Format(Catalog.GetString(
                                                  "The gift batch total ({0}) for batch {1} does not equal the hash total ({2})!"),
                                              StringHelper.FormatUsingCurrencyCode(ACurrentBatchRow.BatchTotal, ACurrentBatchRow.CurrencyCode),
                                              ACurrentBatchRow.BatchNumber,
                                              StringHelper.FormatUsingCurrencyCode(ACurrentBatchRow.HashTotal, ACurrentBatchRow.CurrencyCode)),
                                "Post Gift Batch");

                return(false);
            }

            //Check for missing international exchange rate
            bool IsTransactionInIntlCurrency = false;

            FMyForm.WarnAboutMissingIntlExchangeRate = true;

            if (FMyForm.InternationalCurrencyExchangeRate(ACurrentBatchRow, out IsTransactionInIntlCurrency, true) == 0)
            {
                return(false);
            }

            //Check for zero Donors or Recipients
            if (!ADonorZeroIsValid)
            {
                DataView batchGiftDV = new DataView(FMainDS.AGift);

                batchGiftDV.RowFilter = string.Format("{0}={1} And {2}=0",
                                                      AGiftTable.GetBatchNumberDBName(),
                                                      FSelectedBatchNumber,
                                                      AGiftTable.GetDonorKeyDBName());

                int numDonorZeros = batchGiftDV.Count;

                if (numDonorZeros > 0)
                {
                    string messageListOfOffendingGifts =
                        String.Format(Catalog.GetString(
                                          "Gift Batch {0} contains {1} gift detail(s) with Donor 0000000. Please fix before posting!{2}{2}"),
                                      FSelectedBatchNumber,
                                      numDonorZeros,
                                      Environment.NewLine);

                    string listOfOffendingRows = string.Empty;

                    listOfOffendingRows += "Gift" + Environment.NewLine;
                    listOfOffendingRows += "------------";

                    foreach (DataRowView drv in batchGiftDV)
                    {
                        AGiftRow giftRow = (AGiftRow)drv.Row;

                        listOfOffendingRows += String.Format("{0}{1:0000}",
                                                             Environment.NewLine,
                                                             giftRow.GiftTransactionNumber);
                    }

                    TFrmExtendedMessageBox extendedMessageBox = new TFrmExtendedMessageBox(FMyForm);

                    extendedMessageBox.ShowDialog((messageListOfOffendingGifts + listOfOffendingRows),
                                                  Catalog.GetString("Post Batch Error"), string.Empty,
                                                  TFrmExtendedMessageBox.TButtons.embbOK,
                                                  TFrmExtendedMessageBox.TIcon.embiWarning);

                    return(false);
                }
            }

            if (!ARecipientZeroIsValid)
            {
                DataView batchGiftDetailsDV = new DataView(FMainDS.AGiftDetail);

                batchGiftDetailsDV.RowFilter = string.Format("{0}={1} And {2}=0",
                                                             AGiftDetailTable.GetBatchNumberDBName(),
                                                             FSelectedBatchNumber,
                                                             AGiftDetailTable.GetRecipientKeyDBName());

                int numRecipientZeros = batchGiftDetailsDV.Count;

                if (numRecipientZeros > 0)
                {
                    string messageListOfOffendingGifts =
                        String.Format(Catalog.GetString(
                                          "Gift Batch {0} contains {1} gift detail(s) with Recipient 0000000. Please fix before posting!{2}{2}"),
                                      FSelectedBatchNumber,
                                      numRecipientZeros,
                                      Environment.NewLine);

                    string listOfOffendingRows = string.Empty;

                    listOfOffendingRows += "Gift   Detail" + Environment.NewLine;
                    listOfOffendingRows += "-------------------";

                    foreach (DataRowView drv in batchGiftDetailsDV)
                    {
                        AGiftDetailRow giftDetailRow = (AGiftDetailRow)drv.Row;

                        listOfOffendingRows += String.Format("{0}{1:0000}  {2:00}",
                                                             Environment.NewLine,
                                                             giftDetailRow.GiftTransactionNumber,
                                                             giftDetailRow.DetailNumber);
                    }

                    TFrmExtendedMessageBox extendedMessageBox = new TFrmExtendedMessageBox(FMyForm);

                    extendedMessageBox.ShowDialog((messageListOfOffendingGifts + listOfOffendingRows),
                                                  Catalog.GetString("Post Batch Error"), string.Empty,
                                                  TFrmExtendedMessageBox.TButtons.embbOK,
                                                  TFrmExtendedMessageBox.TIcon.embiWarning);

                    return(false);
                }
            }

            //Check for inactive KeyMinistries
            DataTable GiftsWithInactiveKeyMinistries;
            bool      ModifiedDetails = false;

            if (AWarnOfInactiveValues && TRemote.MFinance.Gift.WebConnectors.InactiveKeyMinistriesFoundInBatch(FLedgerNumber, FSelectedBatchNumber,
                                                                                                               out GiftsWithInactiveKeyMinistries, false))
            {
                int numInactiveValues = GiftsWithInactiveKeyMinistries.Rows.Count;

                string messageNonModifiedBatch =
                    String.Format(Catalog.GetString("Gift Batch {0} contains {1} inactive key ministries. Please fix before posting!{2}{2}"),
                                  FSelectedBatchNumber,
                                  numInactiveValues,
                                  Environment.NewLine);
                string messageModifiedBatch =
                    String.Format(Catalog.GetString(
                                      "Reversal/Adjustment Gift Batch {0} contains {1} inactive key ministries. Do you still want to post?{2}{2}"),
                                  FSelectedBatchNumber,
                                  numInactiveValues,
                                  Environment.NewLine);

                string listOfOffendingRows = string.Empty;

                listOfOffendingRows += "Gift      Detail   Recipient          KeyMinistry" + Environment.NewLine;
                listOfOffendingRows += "-------------------------------------------------------------------------------";

                foreach (DataRow dr in GiftsWithInactiveKeyMinistries.Rows)
                {
                    listOfOffendingRows += String.Format("{0}{1:0000}    {2:00}        {3:00000000000}    {4}",
                                                         Environment.NewLine,
                                                         dr[0],
                                                         dr[1],
                                                         dr[2],
                                                         dr[3]);

                    bool isModified = Convert.ToBoolean(dr[4]);

                    if (isModified)
                    {
                        ModifiedDetails = true;
                    }
                }

                TFrmExtendedMessageBox extendedMessageBox = new TFrmExtendedMessageBox(FMyForm);

                if (ModifiedDetails)
                {
                    if (extendedMessageBox.ShowDialog((messageModifiedBatch + listOfOffendingRows),
                                                      Catalog.GetString("Post Batch"), string.Empty,
                                                      TFrmExtendedMessageBox.TButtons.embbYesNo,
                                                      TFrmExtendedMessageBox.TIcon.embiWarning) == TFrmExtendedMessageBox.TResult.embrYes)
                    {
                        APostingAlreadyConfirmed = true;
                    }
                    else
                    {
                        return(false);
                    }
                }
                else
                {
                    extendedMessageBox.ShowDialog((messageNonModifiedBatch + listOfOffendingRows),
                                                  Catalog.GetString("Post Batch Error"), string.Empty,
                                                  TFrmExtendedMessageBox.TButtons.embbOK,
                                                  TFrmExtendedMessageBox.TIcon.embiWarning);

                    return(false);
                }
            }

            // ask if the user really wants to post the batch
            if (!APostingAlreadyConfirmed &&
                (MessageBox.Show(String.Format(Catalog.GetString("Do you really want to post gift batch {0}?"), FSelectedBatchNumber),
                                 Catalog.GetString("Confirm posting of Gift Batch"),
                                 MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes))
            {
                return(false);
            }

            TVerificationResultCollection Verifications = new TVerificationResultCollection();

            try
            {
                FPostingInProgress = true;

                Thread postingThread = new Thread(() => PostGiftBatch(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();
                    ARefreshGUIAfterPosting = true;
                    return(false);
                }
                else if (!TVerificationHelper.IsNullOrOnlyNonCritical(Verifications))
                {
                    TFrmExtendedMessageBox extendedMessageBox = new TFrmExtendedMessageBox(FMyForm);

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

                    errorMessages.AppendLine(Catalog.GetString("________________________Gift 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!"));
                    ARefreshGUIAfterPosting = true;
                }
            }
            catch (Exception ex)
            {
                TLogging.LogException(ex, Utilities.GetMethodSignature());
                throw;
            }
            finally
            {
                FPostingInProgress = false;
            }

            return(true);
        }
        /// <summary>
        /// Method to cancel a specified batch
        /// </summary>
        /// <param name="ACurrentBatchRow"></param>
        /// <returns></returns>
        public bool CancelBatch(AGiftBatchRow ACurrentBatchRow)
        {
            //Assign default value(s)
            bool CancellationSuccessful = false;

            string CancelMessage     = string.Empty;
            string CompletionMessage = string.Empty;

            List <string> ModifiedDetailKeys = new List <string>();

            if ((ACurrentBatchRow == null) || (ACurrentBatchRow.BatchStatus != MFinanceConstants.BATCH_UNPOSTED))
            {
                return(CancellationSuccessful);
            }

            CancelMessage = String.Format(Catalog.GetString("Are you sure you want to cancel gift batch number: {0}?"),
                                          ACurrentBatchRow.BatchNumber);

            if ((MessageBox.Show(CancelMessage,
                                 "Cancel Batch",
                                 MessageBoxButtons.YesNo,
                                 MessageBoxIcon.Question,
                                 MessageBoxDefaultButton.Button2) != System.Windows.Forms.DialogResult.Yes))
            {
                return(CancellationSuccessful);
            }

            //Backup the Dataset for reversion purposes
            GiftBatchTDS BackupMainDS = (GiftBatchTDS)FMainDS.Copy();

            BackupMainDS.Merge(FMainDS);

            try
            {
                FMyForm.Cursor = Cursors.WaitCursor;

                //Normally need to set the message parameters before the delete is performed if requiring any of the row values
                CompletionMessage = String.Format(Catalog.GetString("Batch no.: {0} cancelled successfully."),
                                                  ACurrentBatchRow.BatchNumber);

                FMyForm.GetBatchControl().UndoModifiedBatchRow(ACurrentBatchRow, true);

                //Load all journals for current Batch
                //clear any transactions currently being editied in the Transaction Tab
                FMyForm.GetTransactionsControl().ClearCurrentSelection();

                //Clear gifts and details etc for current and any other loaded batches
                FMainDS.AGiftDetail.Clear();
                FMainDS.AGift.Clear();

                //Load tables afresh
                FMainDS.Merge(TRemote.MFinance.Gift.WebConnectors.LoadGiftTransactionsForBatch(FLedgerNumber, ACurrentBatchRow.BatchNumber));
                FMainDS.AcceptChanges();

                //Delete gift details
                for (int i = FMainDS.AGiftDetail.Count - 1; i >= 0; i--)
                {
                    // if the gift detail being cancelled is a reversed gift
                    if (FMainDS.AGiftDetail[i].ModifiedDetail && !string.IsNullOrEmpty(FMainDS.AGiftDetail[i].ModifiedDetailKey))
                    {
                        ModifiedDetailKeys.Add(FMainDS.AGiftDetail[i].ModifiedDetailKey);
                    }

                    FMainDS.AGiftDetail[i].Delete();
                }

                //Delete gifts
                for (int i = FMainDS.AGift.Count - 1; i >= 0; i--)
                {
                    FMainDS.AGift[i].Delete();
                }

                //Batch is only cancelled and never deleted
                ACurrentBatchRow.BatchTotal  = 0;
                ACurrentBatchRow.BatchStatus = MFinanceConstants.BATCH_CANCELLED;

                // save first
                if (FMyForm.SaveChanges())
                {
                    TRemote.MFinance.Gift.WebConnectors.RemoveModifiedDetailOnCancel(FLedgerNumber, ModifiedDetailKeys);

                    MessageBox.Show(CompletionMessage,
                                    "Batch Cancelled",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Information);
                }
                else
                {
                    throw new Exception(Catalog.GetString("The batch failed to save after being cancelled! Reopen the form and retry."));
                }

                CancellationSuccessful = true;
            }
            catch (Exception ex)
            {
                CompletionMessage = ex.Message;
                MessageBox.Show(CompletionMessage,
                                "Cancellation Error",
                                MessageBoxButtons.OK,
                                MessageBoxIcon.Error);

                //Revert to previous state
                FMainDS.Merge(BackupMainDS);
            }
            finally
            {
                FMyForm.Cursor = Cursors.Default;
            }

            return(CancellationSuccessful);
        }
Example #5
0
        private bool OnDeleteRowManual(GiftBatchTDSAGiftDetailRow ARowToDelete, ref string ACompletionMessage)
        {
            //TODO: Make this like deleton on GL Transactions form
            // e.g. pass copy to delete method on server...
            //GiftBatchTDS TempDS = (GiftBatchTDS)FMainDS.Copy();
            //TempDS.Merge(FMainDS);

            bool DeletionSuccessful = false;

            ACompletionMessage = string.Empty;

            if (FBatchRow == null)
            {
                FBatchRow = GetBatchRow();
            }

            if ((ARowToDelete == null) || (FBatchRow.BatchStatus != MFinanceConstants.BATCH_UNPOSTED))
            {
                return(false);
            }

            int  CurrentBatchNo   = ARowToDelete.BatchNumber;
            bool RowToDeleteIsNew = (ARowToDelete.RowState == DataRowState.Added);
            int  CurrentRowIndex  = GetSelectedRowIndex();

            TFrmGiftBatch FMyForm = (TFrmGiftBatch)this.ParentForm;

            GiftBatchTDS  BackupMainDS         = null;
            List <string> OriginatingDetailRef = new List <string>();

            int    SelectedDetailNumber        = ARowToDelete.DetailNumber;
            int    GiftToDeleteTransNo         = 0;
            string FilterAllGiftsOfBatch       = String.Empty;
            string FilterAllGiftDetailsOfBatch = String.Empty;

            int DetailRowCount = FGiftDetailView.Count;

            try
            {
                this.Cursor = Cursors.WaitCursor;
                //Specify current action
                FMyForm.FCurrentGiftBatchAction = Logic.TExtraGiftBatchChecks.GiftBatchAction.DELETINGTRANS;
                //Speeds up deletion of larger gift sets
                FMainDS.EnforceConstraints = false;
                // temporarily disable  New Donor Warning
                FMyForm.NewDonorWarning = false;

                //Backup the Dataset for reversion purposes
                BackupMainDS = (GiftBatchTDS)FMainDS.GetChangesTyped(false);

                //Don't run an inactive fields check on this batch
                FMyForm.GetBatchControl().UpdateUnpostedBatchDictionary(CurrentBatchNo);

                if ((ARowToDelete.ModifiedDetailKey != null) && (ARowToDelete.ModifiedDetailKey.Length > 0))
                {
                    OriginatingDetailRef.Add(ARowToDelete.ModifiedDetailKey);
                }

                //Delete current row
                ARowToDelete.RejectChanges();

                if (!RowToDeleteIsNew)
                {
                    ShowDetails(ARowToDelete);
                }

                ARowToDelete.Delete();

                //If there existed (before the delete row above) more than one detail row, then no need to delete gift header row
                if (DetailRowCount > 1)
                {
                    ACompletionMessage = Catalog.GetString("Gift Detail row deleted successfully!");

                    FGiftSelectedForDeletionFlag = false;

                    foreach (DataRowView rv in FGiftDetailView)
                    {
                        GiftBatchTDSAGiftDetailRow row = (GiftBatchTDSAGiftDetailRow)rv.Row;

                        if (row.DetailNumber > SelectedDetailNumber)
                        {
                            row.DetailNumber--;
                        }
                    }

                    FGift.LastDetailNumber--;
                }
                else
                {
                    ACompletionMessage = Catalog.GetString("Gift deleted successfully!");

                    GiftToDeleteTransNo = FGift.GiftTransactionNumber;

                    // Reduce all Gift Detail row Transaction numbers by 1 if they are greater then gift to be deleted
                    FilterAllGiftDetailsOfBatch = String.Format("{0}={1} And {2}>{3}",
                                                                AGiftDetailTable.GetBatchNumberDBName(),
                                                                FBatchNumber,
                                                                AGiftDetailTable.GetGiftTransactionNumberDBName(),
                                                                GiftToDeleteTransNo);

                    DataView giftDetailView = new DataView(FMainDS.AGiftDetail);
                    giftDetailView.RowFilter = FilterAllGiftDetailsOfBatch;
                    giftDetailView.Sort      = String.Format("{0} ASC", AGiftDetailTable.GetGiftTransactionNumberDBName());

                    foreach (DataRowView rv in giftDetailView)
                    {
                        GiftBatchTDSAGiftDetailRow row = (GiftBatchTDSAGiftDetailRow)rv.Row;

                        row.GiftTransactionNumber--;
                    }

                    //Cannot delete the gift row, just copy the data of rows above down by 1 row
                    // and then mark the top row for deletion
                    //In other words, bubble the gift row to be deleted to the top
                    FilterAllGiftsOfBatch = String.Format("{0}={1} And {2}>={3}",
                                                          AGiftTable.GetBatchNumberDBName(),
                                                          FBatchNumber,
                                                          AGiftTable.GetGiftTransactionNumberDBName(),
                                                          GiftToDeleteTransNo);

                    DataView giftView = new DataView(FMainDS.AGift);
                    giftView.RowFilter = FilterAllGiftsOfBatch;
                    giftView.Sort      = String.Format("{0} ASC", AGiftTable.GetGiftTransactionNumberDBName());

                    AGiftRow giftRowToReceive  = null;
                    AGiftRow giftRowToCopyDown = null;
                    AGiftRow giftRowCurrent    = null;

                    int currentGiftTransNo = 0;

                    foreach (DataRowView gv in giftView)
                    {
                        giftRowCurrent = (AGiftRow)gv.Row;

                        currentGiftTransNo = giftRowCurrent.GiftTransactionNumber;

                        if (currentGiftTransNo > GiftToDeleteTransNo)
                        {
                            giftRowToCopyDown = giftRowCurrent;

                            //Copy column values down
                            for (int j = 3; j < giftRowToCopyDown.Table.Columns.Count; j++)
                            {
                                //Update all columns except the pk fields that remain the same
                                if (!giftRowToCopyDown.Table.Columns[j].ColumnName.EndsWith("_text"))
                                {
                                    giftRowToReceive[j] = giftRowToCopyDown[j];
                                }
                            }
                        }

                        if (currentGiftTransNo == FBatchRow.LastGiftNumber)
                        {
                            //Mark last record for deletion
                            giftRowCurrent.GiftStatus = MFinanceConstants.MARKED_FOR_DELETION;
                        }

                        //Will always be previous row
                        giftRowToReceive = giftRowCurrent;
                    }

                    FPreviouslySelectedDetailRow = null;
                    FGiftSelectedForDeletionFlag = true;
                    FBatchRow.LastGiftNumber--;
                }

                //Save and check for inactive values and ex-workers and anonymous gifts
                //  in other unsaved Batches
                FPetraUtilsObject.SetChangedFlag();

                if (!FMyForm.SaveChangesManual(Logic.TExtraGiftBatchChecks.GiftBatchAction.DELETINGTRANS, false, false))
                {
                    FMyForm.GetBatchControl().UpdateUnpostedBatchDictionary();

                    MessageBox.Show(Catalog.GetString("The gift detail has been deleted but the changes are not saved!"),
                                    Catalog.GetString("Deletion Warning"),
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Warning);

                    ACompletionMessage = string.Empty;

                    if (FGiftSelectedForDeletionFlag)
                    {
                        FGiftSelectedForDeletionFlag = false;
                        SetBatchLastGiftNumber();
                        UpdateControlsProtection();
                    }

                    UpdateTotals();

                    return(false);
                }

                //Check if have deleted a reversing gift detail
                if (OriginatingDetailRef.Count > 0)
                {
                    TRemote.MFinance.Gift.WebConnectors.ReversedGiftReset(FLedgerNumber, OriginatingDetailRef);
                }

                //Clear current batch's gift data and reload from server
                RefreshBatchGiftData(FBatchNumber, true);

                DeletionSuccessful = true;
            }
            catch (Exception ex)
            {
                //Revert to previous state
                RevertDataSet(FMainDS, BackupMainDS, CurrentRowIndex);

                TLogging.LogException(ex, Utilities.GetMethodSignature());
                throw;
            }
            finally
            {
                FMyForm.NewDonorWarning         = true;
                FMainDS.EnforceConstraints      = true;
                FMyForm.FCurrentGiftBatchAction = Logic.TExtraGiftBatchChecks.GiftBatchAction.NONE;
                this.Cursor = Cursors.Default;
            }

            SetGiftDetailDefaultView();
            FFilterAndFindObject.ApplyFilter();
            UpdateRecordNumberDisplay();

            return(DeletionSuccessful);
        }
Example #6
0
        /// <summary>
        /// this supports the batch export files from Petra 2.x.
        /// Each line starts with a type specifier, B for batch, J for journal, T for transaction
        /// </summary>
        public void ImportBatches(TGiftImportDataSourceEnum AImportSource, GiftBatchTDS AMainDS)
        {
            bool           ImportOK = false;
            bool           RefreshGUIAfterImport = false;
            OpenFileDialog OFileDialog           = null;

            if (FPetraUtilsObject.HasChanges)
            {
                // saving failed, therefore do not try to import
                MessageBox.Show(Catalog.GetString("Please save before calling this function!"), Catalog.GetString(
                                    "Failure"), MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            ALedgerRow LedgerRow             = (ALedgerRow)AMainDS.ALedger.Rows[0];
            int        CurrentTopBatchNumber = LedgerRow.LastGiftBatchNumber;

            try
            {
                FMyForm.FCurrentGiftBatchAction = Logic.TExtraGiftBatchChecks.GiftBatchAction.IMPORTING;

                bool datesMayBeIntegers = TUserDefaults.GetBooleanDefault(MCommonConstants.USERDEFAULT_IMPORTEDDATESMAYBEINTEGERS, false);
                FdlgSeparator = new TDlgSelectCSVSeparator(false);
                FdlgSeparator.DateMayBeInteger = datesMayBeIntegers;

                if (AImportSource == TGiftImportDataSourceEnum.FromClipboard)
                {
                    string ImportString = Clipboard.GetText(TextDataFormat.UnicodeText);

                    if ((ImportString == null) || (ImportString.Length == 0))
                    {
                        MessageBox.Show(Catalog.GetString("Please first copy data from your spreadsheet application!"),
                                        Catalog.GetString("Failure"), MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }

                    FdlgSeparator.CSVData = ImportString;
                }
                else if (AImportSource == TGiftImportDataSourceEnum.FromFile)
                {
                    OFileDialog = new OpenFileDialog();

                    string exportPath = TClientSettings.GetExportPath();
                    string fullPath   = TUserDefaults.GetStringDefault("Imp Filename",
                                                                       exportPath + Path.DirectorySeparatorChar + "import.csv");
                    TImportExportDialogs.SetOpenFileDialogFilePathAndName(OFileDialog, fullPath, exportPath);

                    OFileDialog.Title  = Catalog.GetString("Import Batches from CSV File");
                    OFileDialog.Filter = Catalog.GetString("Gift Batch Files(*.csv)|*.csv|Text Files(*.txt)|*.txt");

                    // This call fixes Windows7 Open File Dialogs.  It must be the line before ShowDialog()
                    TWin7FileOpenSaveDialog.PrepareDialog(Path.GetFileName(fullPath));

                    if (OFileDialog.ShowDialog() == DialogResult.OK)
                    {
                        Boolean fileCanOpen = FdlgSeparator.OpenCsvFile(OFileDialog.FileName);

                        if (!fileCanOpen)
                        {
                            MessageBox.Show(Catalog.GetString("Unable to open file."),
                                            Catalog.GetString("Gift Import"),
                                            MessageBoxButtons.OK,
                                            MessageBoxIcon.Stop);
                            return;
                        }
                    }
                    else
                    {
                        return;
                    }
                }
                else
                {
                    // unknown source!!
                    return;
                }

                String impOptions       = TUserDefaults.GetStringDefault("Imp Options", ";" + TDlgSelectCSVSeparator.NUMBERFORMAT_AMERICAN);
                String dateFormatString = TUserDefaults.GetStringDefault("Imp Date", "MDY");

                FdlgSeparator.DateFormat        = dateFormatString;
                FdlgSeparator.NumberFormat      = (impOptions.Length > 1) ? impOptions.Substring(1) : TDlgSelectCSVSeparator.NUMBERFORMAT_AMERICAN;
                FdlgSeparator.SelectedSeparator = StringHelper.GetCSVSeparator(FdlgSeparator.FileContent) ??
                                                  ((impOptions.Length > 0) ? impOptions.Substring(0, 1) : ";");

                if (FdlgSeparator.ShowDialog() == DialogResult.OK)
                {
                    Hashtable requestParams = new Hashtable();

                    requestParams.Add("ALedgerNumber", FLedgerNumber);
                    requestParams.Add("Delimiter", FdlgSeparator.SelectedSeparator);
                    requestParams.Add("DateFormatString", FdlgSeparator.DateFormat);
                    requestParams.Add("DatesMayBeIntegers", datesMayBeIntegers);
                    requestParams.Add("NumberFormat", FdlgSeparator.NumberFormat);
                    requestParams.Add("NewLine", Environment.NewLine);

                    bool Repeat = true;

                    while (Repeat)
                    {
                        Repeat = false;

                        TVerificationResultCollection AMessages = new TVerificationResultCollection();
                        GiftBatchTDSAGiftDetailTable  NeedRecipientLedgerNumber = new GiftBatchTDSAGiftDetailTable();

                        Thread ImportThread = new Thread(() => ImportGiftBatches(
                                                             requestParams,
                                                             FdlgSeparator.FileContent,
                                                             out AMessages,
                                                             out ImportOK,
                                                             out RefreshGUIAfterImport,
                                                             out NeedRecipientLedgerNumber));

                        using (TProgressDialog ImportDialog = new TProgressDialog(ImportThread))
                        {
                            ImportDialog.ShowDialog();
                        }

                        // If NeedRecipientLedgerNumber contains data then AMessages will only ever contain
                        // one message alerting the user that no data has been imported.
                        // We do not want to show this as we will be displaying another more detailed message.
                        if (NeedRecipientLedgerNumber.Rows.Count == 0)
                        {
                            if (TVerificationHelper.ResultsContainErrorCode(AMessages, PetraErrorCodes.ERR_DB_SERIALIZATION_EXCEPTION))
                            {
                                TConcurrentServerTransactions.ShowTransactionSerializationExceptionDialog();
                            }
                            else
                            {
                                ShowMessages(AMessages);
                            }
                        }

                        // if the import contains gifts with Motivation Group 'GIFT' and that have a Family recipient with no Gift Destination
                        // then the import will have failed and we need to alert the user
                        if (NeedRecipientLedgerNumber.Rows.Count > 0)
                        {
                            bool OfferToRunImportAgain            = true;
                            bool DoNotShowMessageBoxEverytime     = false;
                            TFrmExtendedMessageBox.TResult Result = TFrmExtendedMessageBox.TResult.embrUndefined;
                            int count = 1;

                            // for each gift in which the recipient needs a Git Destination
                            foreach (GiftBatchTDSAGiftDetailRow Row in NeedRecipientLedgerNumber.Rows)
                            {
                                if (!DoNotShowMessageBoxEverytime)
                                {
                                    string CheckboxText = string.Empty;

                                    // only show checkbox if there is at least one more occurrence of this error
                                    if (NeedRecipientLedgerNumber.Rows.Count - count > 0)
                                    {
                                        CheckboxText = string.Format(
                                            Catalog.GetString(
                                                "Do this for all further occurrences ({0})?"), NeedRecipientLedgerNumber.Rows.Count - count);
                                    }

                                    TFrmExtendedMessageBox extendedMessageBox = new TFrmExtendedMessageBox(FPetraUtilsObject.GetForm());

                                    extendedMessageBox.ShowDialog(string.Format(
                                                                      Catalog.GetString(
                                                                          "Gift Import has been cancelled as the recipient '{0}' ({1}) has no Gift Destination assigned."),
                                                                      Row.RecipientDescription, Row.RecipientKey) +
                                                                  "\n\r\n\r\n\r" +
                                                                  Catalog.GetString("Do you want to assign a Gift Destination to this partner now?"),
                                                                  Catalog.GetString("Import Errors"),
                                                                  CheckboxText,
                                                                  TFrmExtendedMessageBox.TButtons.embbYesNo, TFrmExtendedMessageBox.TIcon.embiWarning);
                                    Result = extendedMessageBox.GetResult(out DoNotShowMessageBoxEverytime);
                                }

                                if (Result == TFrmExtendedMessageBox.TResult.embrYes)
                                {
                                    // allow the user to assign a Gift Destingation
                                    TFrmGiftDestination GiftDestinationForm = new TFrmGiftDestination(FPetraUtilsObject.GetForm(), Row.RecipientKey);
                                    GiftDestinationForm.ShowDialog();
                                }
                                else
                                {
                                    OfferToRunImportAgain = false;

                                    if (DoNotShowMessageBoxEverytime)
                                    {
                                        break;
                                    }
                                }

                                count++;
                            }

                            // if the user has clicked yes to assigning Gift Destinations then offer to restart the import
                            if (OfferToRunImportAgain &&
                                (MessageBox.Show(Catalog.GetString("Would you like to import this Gift Batch again?"),
                                                 Catalog.GetString("Gift Import"), MessageBoxButtons.YesNo, MessageBoxIcon.Question,
                                                 MessageBoxDefaultButton.Button2)
                                 == DialogResult.Yes))
                            {
                                Repeat = true;
                            }
                        }
                    }
                }

                // We save the defaults even if ok is false - because the client will probably want to try and import
                //   the same file again after correcting any errors
                SaveUserDefaults(OFileDialog);

                if (ImportOK)
                {
                    MessageBox.Show(Catalog.GetString("Your data was imported successfully!"),
                                    Catalog.GetString("Gift Import"),
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Information);
                }

                if (ImportOK)
                {
                    FMyUserControl.LoadBatchesForCurrentYear();
                    FMyForm.GetBatchControl().SelectRowInBatchGrid(1);

                    DataView allNewBatches = new DataView(AMainDS.AGiftBatch);

                    allNewBatches.RowFilter = String.Format("{0} > {1}",
                                                            AGiftBatchTable.GetBatchNumberDBName(),
                                                            CurrentTopBatchNumber);

                    foreach (DataRowView drv in allNewBatches)
                    {
                        drv.Row.SetModified();
                    }

                    FPetraUtilsObject.SetChangedFlag();
                    //Force initial inactive values check
                    FMyForm.SaveChangesManual(FMyForm.FCurrentGiftBatchAction);
                }
                else if (RefreshGUIAfterImport)
                {
                    FMyUserControl.LoadBatchesForCurrentYear();
                    FMyForm.GetBatchControl().SelectRowInBatchGrid(1);
                }
            }
            finally
            {
                FMyForm.FCurrentGiftBatchAction = Logic.TExtraGiftBatchChecks.GiftBatchAction.NONE;
            }
        }