context: //
  // DO NOT REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  //
  // @Authors:
  //       timop
  //
  // Copyright 2004-2011 by OM International
  //
  // This file is part of OpenPetra.org.
  //
  // OpenPetra.org is free software: you can redistribute it and/or modify
  // it under the terms of the GNU General Public License as published by
  // the Free Software Foundation, either version 3 of the License, or
  // (at your option) any later version.
  //
  // OpenPetra.org is distributed in the hope that it will be useful,
  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  // GNU General Public License for more details.
  //
  // You should have received a copy of the GNU General Public License
  // along with OpenPetra.org.  If not, see <http://www.gnu.org/licenses/>.
  //
  using System;
  using System.Data;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Windows.Forms;
  
  using Ict.Common;
  using Ict.Common.Verification;
  using Ict.Petra.Client.App.Core;
  using Ict.Petra.Client.App.Core.RemoteObjects;
  using Ict.Petra.Client.App.Gui;
  using Ict.Petra.Client.CommonForms;
  using Ict.Petra.Client.MFinance.Logic;
  using Ict.Petra.Client.MPartner.Gui;
  using Ict.Petra.Client.MReporting.Gui.MFinance;
  using Ict.Petra.Shared;
  using Ict.Petra.Shared.MFinance;
  using Ict.Petra.Shared.MFinance.Gift.Data;
  using Ict.Petra.Shared.MPartner;
  
  namespace Ict.Petra.Client.MFinance.Gui.Gift
  {
      public partial class TFrmGiftBatch : IFrmPetraEditManual
      {
          private Int32 FLedgerNumber;
          private Boolean FViewMode = false;
  
          private GiftBatchTDS FViewModeTDS;
          private int standardTabIndex = 0;
          private bool FNewDonorWarning = true;
          private bool FWarnAboutMissingIntlExchangeRate = false;
          // changed gift records
          GiftBatchTDSAGiftDetailTable FGiftDetailTable = null;
  
          // Variables that are used to select a specific batch on startup
          private Int32 FInitialBatchNumber = -1;
          private Int32 FInitialBatchYear = -1;
  
          private Boolean FLatestSaveIncludedForex = false;
  
          /// ViewMode is a special mode where the whole window with all tabs is in a readonly mode
          public bool ViewMode {
              get
              {
                  return FViewMode;
              }
              set
              {
                  FViewMode = value;
              }
          }
  
          /// ViewModeTDS is for injection of the Datasets in the View Mode
          public GiftBatchTDS ViewModeTDS
          {
              get
              {
                  return FViewModeTDS;
              }
              set
              {
                  FViewModeTDS = value;
              }
          }
  
          /// <summary>
          /// Set this property if you want to load the screen with an initial Year/Batch/Journal
          /// </summary>
          public Int32 InitialBatchYear
          {
              set
              {
                  FInitialBatchYear = value;
              }
              get
              {
                  return FInitialBatchYear;
              }
          }
  
          /// <summary>
          /// Set this property if you want to load the screen with an initial Year/Batch/Journal
          /// </summary>
          public Int32 InitialBatchNumber
          {
              set
              {
                  FInitialBatchNumber = value;
              }
              get
              {
                  return FInitialBatchNumber;
              }
          }
  
          /* Be sure to leave the LedgerNumber property in this position in the code
           * AFTER the ones above.   Otherwise the code will not work that opens this
           * screen at a pre-defined batch or in ViewMode.*/
  
          /// <summary>
          /// use this ledger
          /// </summary>
          public Int32 LedgerNumber
          {
              set
              {
                  FLedgerNumber = value;
  
                  // setting the ledger number on the batch screen will automatically trigger loading the batches for the current year
                  ucoBatches.LedgerNumber = value;
  
                  this.Text += " - " + TFinanceControls.GetLedgerNumberAndName(FLedgerNumber);
  
                  //Enable below if want code to run before standard Save() is executed
                  FPetraUtilsObject.DataSavingStarted += new TDataSavingStartHandler(FPetraUtilsObject_DataSavingStarted);
              }
          }
  
          /// <summary>
          /// Show the user a message when a gift is entered for a new donor
          /// </summary>
          public bool NewDonorWarning
          {
              set
              {
                  FNewDonorWarning = value;
              }
          }
  
          /// <summary>
          /// show the actual data of the database after server has changed data
          /// </summary>
          public void RefreshAll()
          {
              ucoBatches.RefreshAllData();
          }
  
          private void FileSaveManual(object sender, EventArgs e)
          {
              SaveChangesManual();
          }
  
          /// <summary>
          /// Check for ExWorkers before saving
          /// </summary>
          /// <returns>True if Save is successful</returns>
          public bool SaveChangesManual()
          {
              return SaveChangesManual(TExtraGiftBatchChecks.GiftBatchAction.SAVING);
          }
  
          /// <summary>
          /// Check for ExWorkers before saving or cancelling
          /// </summary>
          /// <returns>True if Save is successful</returns>
          public bool SaveChangesManual(TExtraGiftBatchChecks.GiftBatchAction AAction)
          {
              GetDataFromControls();
  
              // first alert the user to any recipients who are Ex-Workers
              if (TExtraGiftBatchChecks.CanContinueWithAnyExWorkers(AAction, FMainDS, FPetraUtilsObject))
              {
                  return SaveChanges();
              }
  
              return false;
          }
  
          /// <summary>
          /// Checks to be made before saving and posting
          /// </summary>
          /// <param name="APostingGiftDetails">GiftDetails for the batch that is to be posted</param>
          /// <param name="ACancelledDueToExWorkerOrAnonDonor">True if batch posting has been cancelled by the user because of an Ex-Worker recipient
          /// or an anonymous donor for a gift that is not marked as confidential</param>
          /// <returns>True if Save is successful</returns>
          public bool SaveChangesForPosting(DataTable APostingGiftDetails, out bool ACancelledDueToExWorkerOrAnonDonor)
          {
              GetDataFromControls();
  
              // first alert the user to any recipients who are Ex-Workers
              ACancelledDueToExWorkerOrAnonDonor = !TExtraGiftBatchChecks.CanContinueWithAnyExWorkers(TExtraGiftBatchChecks.GiftBatchAction.POSTING,
                  FMainDS,
                  FPetraUtilsObject,
                  APostingGiftDetails);
  
              // if save is continuing then alert the user to any gift that are not marked confidential but have an anonymous donor
              if (!ACancelledDueToExWorkerOrAnonDonor)
              {
                  ACancelledDueToExWorkerOrAnonDonor = !TExtraGiftBatchChecks.CanContinueWithAnyAnonymousDonors(FMainDS);
              }
  
              if (!ACancelledDueToExWorkerOrAnonDonor)
              {
                  return SaveChanges();
              }
  
              return false;
          }
  
          // Before the dataset is saved, check for correlation between batch and transactions
          private void FPetraUtilsObject_DataSavingStarted(object Sender, EventArgs e)
          {
              ucoBatches.CheckBeforeSaving();
              ucoTransactions.CheckBeforeSaving();
  
              if (FNewDonorWarning)
              {
                  FPetraUtilsObject_DataSavingStarted_NewDonorWarning();
              }
          }
  
          // This manual method lets us peek at the data that is about to be saved...
          // The data has already been collected from the contols and validated and there is definitely something to save...
          private TSubmitChangesResult StoreManualCode(ref GiftBatchTDS SubmitDS, out TVerificationResultCollection VerificationResult)
          {
              FLatestSaveIncludedForex = false;
  
              if (SubmitDS.AGiftBatch != null)
              {
                  // Check whether we are saving any rows that are in foreign currency
                  DataView dv = new DataView(SubmitDS.AGiftBatch,
                      String.Format("{0}<>'{1}'", AGiftBatchTable.GetCurrencyCodeDBName(), FMainDS.ALedger[0].BaseCurrency),
                      String.Empty, DataViewRowState.CurrentRows);
                  FLatestSaveIncludedForex = (dv.Count > 0);
              }
  
              // Now do the standard call to save the changes
              return TRemote.MFinance.Gift.WebConnectors.SaveGiftBatchTDS(ref SubmitDS, out VerificationResult);
          }
  
          private void FPetraUtilsObject_DataSaved(object Sender, TDataSavedEventArgs e)
          {
              if (FNewDonorWarning)
              {
                  FPetraUtilsObject_DataSaved_NewDonorWarning(Sender, e);
              }
  
              if (e.Success && FLatestSaveIncludedForex)
              {
                  // Notify the exchange rate screen, if it is there
                  TFormsMessage broadcastMessage = new TFormsMessage(TFormsMessageClassEnum.mcGLOrGiftBatchSaved, this.ToString());
                  TFormsList.GFormsList.BroadcastFormMessage(broadcastMessage);
              }
          }
  
          private void FPetraUtilsObject_DataSavingStarted_NewDonorWarning()
          {
              GetDataFromControls();
  
              FGiftDetailTable = FMainDS.AGiftDetail.GetChangesTyped();
          }
  
          private void FPetraUtilsObject_DataSaved_NewDonorWarning(object Sender, TDataSavedEventArgs e)
          {
              // if data successfully saved then look for new donors and warn the user
              if (e.Success && (FGiftDetailTable != null) && FNewDonorWarning)
              {
                  // this list contains a list of all new donors that were entered onto form
                  List <Int64>NewDonorsList = ucoTransactions.NewDonorsList;
  
                  foreach (GiftBatchTDSAGiftDetailRow Row in FGiftDetailTable.Rows)
                  {
                      // check changed data is either added or modified and that it is by a new donor
                      if (((Row.RowState == DataRowState.Added) || (Row.RowState == DataRowState.Modified))
                          && (!Row.IsDonorKeyNull() && NewDonorsList.Contains(Row.DonorKey)))
                      {
                          if (MessageBox.Show(string.Format(Catalog.GetString(
                                          "{0} ({1}) is a new Donor.{2}Do you want to add subscriptions for them?{2}" +
                                          "(Note: this message can be disabled in the 'File' menu by unselecting the 'New Donor Warning' item.)"),
                                      Row.DonorName, Row.DonorKey, "\n\n"),
                                  Catalog.GetString("New Donor"), MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                          {
                              // Open the donor's Edit screen so subscriptions can be added
                              TFrmPartnerEdit frm = new TFrmPartnerEdit(FPetraUtilsObject.GetForm());
  
                              frm.SetParameters(TScreenMode.smEdit, Row.DonorKey, TPartnerEditTabPageEnum.petpSubscriptions);
                              frm.ShowDialog();
                          }
  
                          // ensures message is not displayed twice for one new donor with two gifts
                          NewDonorsList.Remove(Row.DonorKey);
                      }
                  }
  
                  ucoTransactions.NewDonorsList.Clear();
              }
          }
  
          private void InitializeManualCode()
          {
              tabGiftBatch.Selecting += new TabControlCancelEventHandler(TabSelectionChanging);
              this.tpgTransactions.Enabled = false;
  
              // get user default
              FNewDonorWarning = TUserDefaults.GetBooleanDefault(TUserDefaults.FINANCE_NEW_DONOR_WARNING, true);
              mniNewDonorWarning.Checked = FNewDonorWarning;
  
              // only add this event if the user want a new donor warning (this will still work without the condition)
              if (FNewDonorWarning)
              {
                  FPetraUtilsObject.DataSaved += new TDataSavedHandler(FPetraUtilsObject_DataSaved);
              }
  
              mniPrintGiftBatchDetail.Enabled = true;
  
              // change the event that gets called when 'Save' is clicked (i.e. changed from generated code)
              tbbSave.Click -= FileSave;
              mniFileSave.Click -= FileSave;
              tbbSave.Click += FileSaveManual;
              mniFileSave.Click += FileSaveManual;
          }
  
          /// <summary>
          /// Handles the click event for filter/find.
          /// </summary>
          /// <param name="sender">Pass this on to the user control.</param>
          /// <param name="e">Not evaluated.</param>
          public void MniFilterFind_Click(object sender, System.EventArgs e)
          {
              switch (tabGiftBatch.SelectedIndex)
              {
                  case (int)eGiftTabs.Batches:
                      ucoBatches.MniFilterFind_Click(sender, e);
                      break;
  
                  case (int)eGiftTabs.Transactions:
                      ucoTransactions.ReconcileKeyMinistryFromCombo();
                      ucoTransactions.MniFilterFind_Click(sender, e);
                      break;
              }
          }
  
          private void TFrmGiftBatch_Load(object sender, EventArgs e)
          {
              FPetraUtilsObject.TFrmPetra_Load(sender, e);
  
              tabGiftBatch.SelectedIndex = standardTabIndex;
              TabSelectionChanged(null, null); //tabGiftBatch.Selecting += new TabControlCancelEventHandler(TabSelectionChanging);
  
              this.Shown += delegate
              {
                  // This will ensure the grid gets the focus when the screen is shown for the first time
                  ucoBatches.SetInitialFocus();
              };
          }
  
          private void RunOnceOnActivationManual()
          {
              ucoBatches.Focus();
              HookupAllInContainer(ucoBatches);
              HookupAllInContainer(ucoTransactions);
          }
  
          /// <summary>
          /// activate the transactions tab and load the gift transactions of the batch
          /// </summary>
          /// <param name="ALedgerNumber"></param>
          /// <param name="ABatchNumber"></param>
          /// <param name="ABatchStatus"></param>
          /// <returns>True if new transactions were actually loaded, False if transactions have already been loaded for the ledger/batch</returns>
          public bool LoadTransactions(Int32 ALedgerNumber, Int32 ABatchNumber,
              string ABatchStatus = MFinanceConstants.BATCH_UNPOSTED)
          {
              return this.ucoTransactions.LoadGifts(ALedgerNumber, ABatchNumber, ABatchStatus);
          }
  
          /// <summary>
          /// this should be called when all data is reloaded after posting
          /// </summary>
          public void ClearCurrentSelections()
          {
              if (this.ucoBatches != null)
              {
                  this.ucoBatches.ClearCurrentSelection();
              }
  
              if (this.ucoTransactions != null)
              {
                  this.ucoTransactions.ClearCurrentSelection();
              }
          }
  
          /// enable the transaction tab page
          public void EnableTransactions(bool AEnable = true)
          {
              this.tpgTransactions.Enabled = AEnable;
          }
  
          /// <summary>
          /// disable the transactions tab if we have no active journal
          /// </summary>
          public void DisableTransactions()
          {
              this.tpgTransactions.Enabled = false;
          }
  
          /// <summary>
          /// disable the batches tab
          /// </summary>
          public void DisableBatches()
          {
              this.tpgBatches.Enabled = false;
          }
  
          /// <summary>
          /// directly access the batches control
          /// </summary>
          public TUC_GiftBatches GetBatchControl()
          {
              return ucoBatches;
          }
  
          /// <summary>
          /// directly access the transactions control
          /// </summary>
          public TUC_GiftTransactions GetTransactionsControl()
          {
              return ucoTransactions;
          }
  
          /// this window contains 2 tabs
          public enum eGiftTabs
          {
              /// list of batches
              Batches,
  
              /// list of transactions
              Transactions
          };
  
          void TabSelectionChanging(object sender, TabControlCancelEventArgs e)
          {
              FPetraUtilsObject.VerificationResultCollection.Clear();
  
              if (!ValidateAllData(false, true))
              {
                  e.Cancel = true;
  
                  FPetraUtilsObject.VerificationResultCollection.FocusOnFirstErrorControlRequested = true;
              }
          }
  
          private void SelectTabManual(int ASelectedTabIndex)
          {
              if (ASelectedTabIndex == (int)eGiftTabs.Batches)
              {
                  SelectTab(eGiftTabs.Batches);
              }
              else
              {
                  SelectTab(eGiftTabs.Transactions);
              }
          }
  
          /// <summary>
          /// Switch to the given tab
          /// </summary>
          /// <param name="ATab"></param>
          public void SelectTab(eGiftTabs ATab)
          {
              FPetraUtilsObject.RestoreAdditionalWindowPositionProperties();
  
              if (ATab == eGiftTabs.Batches)
              {
                  this.tabGiftBatch.SelectedTab = this.tpgBatches;
                  this.tpgTransactions.Enabled = (ucoBatches.GetSelectedDetailRow() != null);
                  this.ucoBatches.SetFocusToGrid();
              }
              else if (ATab == eGiftTabs.Transactions)
              {
                  if (this.tpgTransactions.Enabled)
                  {
                      // Note!! This call may result in this (SelectTab) method being called again (but no new transactions will be loaded the second time)
                      this.tabGiftBatch.SelectedTab = this.tpgTransactions;
  
  
gt:                     AGiftBatchRow SelectedRow = ucoBatches.GetSelectedDetailRow();