context: //
  // DO NOT REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  //
  // @Authors:
  //       christiank, timop
  //
  // Copyright 2004-2013 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.Collections;
  using System.Collections.Specialized;
  using System.Data;
  using System.Data.Odbc;
  using GNU.Gettext;
  using Ict.Common;
  using Ict.Common.Data;
  using Ict.Common.DB;
  using Ict.Common.Exceptions;
  using Ict.Common.Verification;
  using Ict.Petra.Shared;
  using Ict.Petra.Shared.MPartner;
  using Ict.Petra.Shared.MPartner.Mailroom.Data;
  using Ict.Petra.Shared.MPartner.Partner.Data;
  using Ict.Petra.Server.MPartner.Mailroom.Data.Access;
  using Ict.Petra.Server.MPartner.Partner.Data.Access;
  
  namespace Ict.Petra.Server.MPartner.DataAggregates
  {
      /// <summary>
      /// The TPPartnerAddressAggregate Class contains logic to create, edit and delete
      /// addresses, involving both p_location and p_partner_location tables.
      /// </summary>
      public class TPPartnerAddressAggregate
      {
          private static void DebugLoadedDataset(DataSet ADataSet)
          {
              TLogging.Log("Select done in TPPartnerAddressAggregate.GetData(). Result: ");
  
              foreach (DataRow TheRow in ADataSet.Tables[PLocationTable.GetTableName()].Rows)
              {
                  TLogging.Log(PLocationTable.GetTableName() + ": Processing rows...");
                  TLogging.Log(TheRow[0].ToString() + " | " + TheRow[1].ToString());
              }
  
              foreach (DataRow TheRow in ADataSet.Tables[PPartnerLocationTable.GetTableName()].Rows)
              {
                  TLogging.Log(PPartnerLocationTable.GetTableName() + ": Processing rows...");
                  TLogging.Log(TheRow[0].ToString() + " | " + TheRow[1].ToString());
              }
          }
  
          /// <summary>
          /// Passes Partner Address data as a DataSet to the caller. Loads all available
          /// Addresses for the Partner.
          ///
          /// </summary>
          /// <param name="ADataSet">DataSet that holds a DataSet with a DataTable for the
          /// Person</param>
          /// <param name="APartnerKey">PartnerKey of the Partner for which Address data is to be
          /// loaded</param>
          /// <param name="AReadTransaction">Transaction for the SELECT statement
          /// </param>
          /// <returns>void</returns>
          public static void LoadAll(DataSet ADataSet, Int64 APartnerKey, TDBTransaction AReadTransaction)
          {
              PLocationTable LocationDT;
              PPartnerLocationTable PartnerLocationDT;
  
              PPartnerLocationAccess.LoadViaPPartner(ADataSet, APartnerKey, AReadTransaction);
              PLocationAccess.LoadViaPPartner(ADataSet, APartnerKey, AReadTransaction);
  
              // Apply security
              LocationDT = (PLocationTable)ADataSet.Tables[PLocationTable.GetTableName()];
              PartnerLocationDT = (PPartnerLocationTable)ADataSet.Tables[PPartnerLocationTable.GetTableName()];
              ApplySecurity(ref PartnerLocationDT, ref LocationDT);
  
              // make sure that location specific fields in PartnerLocationDT get initialized
              if (ADataSet.GetType() == typeof(PartnerEditTDS))
              {
                  PartnerCodeHelper.SyncPartnerEditTDSPartnerLocation(LocationDT, (PartnerEditTDSPPartnerLocationTable)PartnerLocationDT);
              }
  
              if (TLogging.DL >= 9)
              {
                  DebugLoadedDataset(ADataSet);
              }
          }
  
          /// <summary>
          /// check the location change; validate and take other required action
          /// eg. change the location of family members, promote address changes
          /// </summary>
          /// <param name="ALocationRow"></param>
          /// <param name="APartnerKey"></param>
          /// <param name="AResponseDS"></param>
          /// <param name="ASubmitChangesTransaction"></param>
          /// <param name="AAddressAddedPromotionDT"></param>
          /// <param name="AChangeLocationParametersDT"></param>
          /// <param name="APartnerLocationTable"></param>
          /// <param name="AVerificationResult"></param>
          /// <param name="ACreateLocation"></param>
          /// <param name="AOriginalLocationKey"></param>
          /// <returns></returns>
          private static TSubmitChangesResult PerformLocationChangeChecks(PLocationRow ALocationRow,
              Int64 APartnerKey,
              ref PartnerAddressAggregateTDS AResponseDS,
              TDBTransaction ASubmitChangesTransaction,
              ref PartnerAddressAggregateTDSAddressAddedOrChangedPromotionTable AAddressAddedPromotionDT,
              ref PartnerAddressAggregateTDSChangePromotionParametersTable AChangeLocationParametersDT,
              ref PPartnerLocationTable APartnerLocationTable,
              ref TVerificationResultCollection AVerificationResult,
              out Boolean ACreateLocation,
              out TLocationPK AOriginalLocationKey)
          {
              TSubmitChangesResult ReturnValue;
              DataView PropagateLocationParametersDV;
              DataView PropagateLocationParametersDV2;
              Boolean UpdateLocation;
  
              Int64[] CreateLocationOtherPartnerKeys;
              PartnerAddressAggregateTDSChangePromotionParametersTable ChangePromotionParametersDT;
              PLocationTable NewLocationTable;
              PLocationRow NewLocationRowSaved;
              Int32 NewLocationLocationKey;
              PPartnerLocationRow PartnerLocationRowForChangedLocation;
  
              DataSet PartnerLocationModifyDS;
              int Counter;
              Int64 OldLocationKey;
              OdbcParameter[] ParametersArray;
              String OtherPartnerKeys = "";
  
              AOriginalLocationKey = null;
  //          TLogging.LogAtLevel(9, "PerformLocationChangeChecks: AAddressAddedPromotionDT.Rows.Count: " + AAddressAddedPromotionDT.Rows.Count.ToString());
  
              if (CheckLocationChange(ALocationRow, APartnerKey, ref AAddressAddedPromotionDT, ASubmitChangesTransaction, out UpdateLocation,
                      out ACreateLocation, out CreateLocationOtherPartnerKeys, out ChangePromotionParametersDT))
              {
                  // Check if there is a Parameter Row for the LocationKey we are looking at
                  PropagateLocationParametersDV = new DataView(AAddressAddedPromotionDT,
                      PartnerAddressAggregateTDSAddressAddedOrChangedPromotionTable.GetSiteKeyDBName() + " = " + ALocationRow.SiteKey.ToString() +
                      " AND " +
                      PartnerAddressAggregateTDSAddressAddedOrChangedPromotionTable.GetLocationKeyDBName() + " = " +
                      ALocationRow.LocationKey.ToString() +
                      " AND " + PartnerAddressAggregateTDSAddressAddedOrChangedPromotionTable.GetLocationChangeDBName() + " = true AND " +
                      PartnerAddressAggregateTDSAddressAddedOrChangedPromotionTable.GetAnswerProcessedClientSideDBName() + " = false",
                      "",
                      DataViewRowState.CurrentRows);
  
                  if (PropagateLocationParametersDV.Count > 0)
                  {
  //                  TLogging.LogAtLevel(9, "PerformLocationChangeChecks: Location " + ALocationRow.LocationKey.ToString() +
  //                          ": Location has been changed, decision on propagation is needed.");
  
                      /*
                       * More information is needed (usually via user interaction)
                       * -> stop processing here and return parameters
                       * (usually used for UI interaction)
                       */
                      if (AResponseDS == null)
                      {
  //                      TLogging.LogAtLevel(9, TLogging.Log("PerformLocationChangeChecks: Creating AResponseDS.");
                          AResponseDS = new PartnerAddressAggregateTDS(MPartnerConstants.PARTNERADDRESSAGGREGATERESPONSE_DATASET);
                      }
  
  //                  TLogging.LogAtLevel(9, "PerformLocationChangeChecks: AAddressAddedPromotionDT.Rows.Count: " + AAddressAddedPromotionDT.Rows.Count.ToString());
                      AResponseDS.Merge(AAddressAddedPromotionDT);
  //                  TLogging.LogAtLevel(9, "PerformLocationChangeChecks: Merged AAddressAddedPromotionDT into AResponseDS.");
                      AResponseDS.Merge(ChangePromotionParametersDT);
  //                  TLogging.LogAtLevel(9, "PerformLocationChangeChecks: Merged ChangePromotionParametersDT into AResponseDS.");
  //                  TLogging.LogAtLevel(9, "PerformLocationChangeChecks: AResponseDS.Tables[" + MPartnerConstants.ADDRESSADDEDORCHANGEDPROMOTION_TABLENAME +
  //                      "].Rows.Count: " + AResponseDS.Tables[MPartnerConstants.ADDRESSADDEDORCHANGEDPROMOTION_TABLENAME].Rows.Count.ToString());
                      return TSubmitChangesResult.scrInfoNeeded;
                  }
                  else
                  {
  //                  TLogging.LogAtLevel(9, "PerformLocationChangeChecks: User made his/her choice regarding Location Change promotion; now processing...");
  
                      /*
                       * User made his/her choice regarding Location Change promotion; now process it
                       */
                      if (ACreateLocation)
                      {
                          OldLocationKey = ALocationRow.LocationKey;
                          AOriginalLocationKey = new TLocationPK(
                              Convert.ToInt64(ALocationRow[PLocationTable.GetSiteKeyDBName(),
                                                           DataRowVersion.Original]),
                              Convert.ToInt32(ALocationRow[PLocationTable.GetLocationKeyDBName(),
                                                           DataRowVersion.Original]));
  
                          // ALocationRow.LocationKey;
  //                      TLogging.LogAtLevel(9, "PerformLocationChangeChecks: Location " + AOriginalLocationKey.LocationKey.ToString() + ": should be created.");
  
                          /*
                           * Create and save NEW Location that holds the same data than the changed
                           * Location.
                           */
                          NewLocationTable = new PLocationTable();
                          NewLocationRowSaved = NewLocationTable.NewRowTyped(false);
                          NewLocationRowSaved.ItemArray = DataUtilities.DestinationSaveItemArray(NewLocationRowSaved, ALocationRow);
                          NewLocationRowSaved.LocationKey = -1;
                          NewLocationTable.Rows.Add(NewLocationRowSaved);
  
                          // Submit the NEW Location to the DB
                          PLocationAccess.SubmitChanges(NewLocationTable, ASubmitChangesTransaction);
  
                          // The DB gives us a LocationKey from a Sequence. Remember this one.
                          NewLocationLocationKey = (Int32)NewLocationRowSaved.LocationKey;
  //                      TLogging.LogAtLevel(9, "PerformLocationChangeChecks: New Location created! Its Location Key is: " + NewLocationLocationKey.ToString());
  
                          // Add the new row to the LocationTable that is beeing processed as well
                          // NewLocationCurrentTableRow := (ALocationRow.Table as PLocationTable).NewRowTyped(false);
                          // NewLocationCurrentTableRow.ItemArray := NewLocationRowSaved.ItemArray;
                          // ALocationRow.Table.Rows.Add(NewLocationCurrentTableRow);
                          // Make the row unchanged so that it isn't picked up as a 'new Address'
                          // and that it doesn't get saved later. Will be sent back to the Partner
                          // Edit screen lateron.
                          // NewLocationCurrentTableRow.AcceptChanges;
  
                          /*
                           * Update the reference from the changed Location to the new Location in
                           * the Partner's PartnerLocation DataTable. This will be saved later in
                           * the call to SubmitChanges in the main loop of the SubmitData function.
                           */
                          PartnerLocationRowForChangedLocation =
                              (PPartnerLocationRow)APartnerLocationTable.Rows.Find(new object[] { APartnerKey, ALocationRow.SiteKey,
                                                                                                  ALocationRow.LocationKey });
                          PartnerLocationRowForChangedLocation.LocationKey = NewLocationLocationKey;
  
                          // Now delete the changed Location so that it doesn't get saved!
                          // ALocationRow.Delete;
                          // ALocationRow.AcceptChanges;
                          // Overwrite the Location that should be replaced with the data of the new Location
                          ALocationRow.ItemArray = NewLocationRowSaved.ItemArray;
                          PropagateLocationParametersDV2 = new DataView(AAddressAddedPromotionDT,
                              PartnerAddressAggregateTDSAddressAddedOrChangedPromotionTable.GetSiteKeyDBName() + " = " +
                              NewLocationRowSaved.SiteKey.ToString() + " AND " +
                              PartnerAddressAggregateTDSAddressAddedOrChangedPromotionTable.GetLocationKeyDBName() + " = " +
                              OldLocationKey.ToString() +
                              " AND " + PartnerAddressAggregateTDSAddressAddedOrChangedPromotionTable.GetLocationChangeDBName() + " = true AND " +
                              PartnerAddressAggregateTDSAddressAddedOrChangedPromotionTable.GetAnswerProcessedClientSideDBName() + " = true",
                              "",
                              DataViewRowState.CurrentRows);
                          ((PartnerAddressAggregateTDSAddressAddedOrChangedPromotionRow)(PropagateLocationParametersDV2[0].Row)).LocationKey =
                              ALocationRow.LocationKey;
  
                          if (CreateLocationOtherPartnerKeys.Length > 0)
                          {
  //                          TLogging.LogAtLevel(9, "PerformLocationChangeChecks: Created Location " + NewLocationLocationKey.ToString() +
  //                              ": should be assigned to " + Convert.ToInt32(CreateLocationOtherPartnerKeys.Length).ToString() + " Partners...");
  
                              // Build list of PartnerKeys for IN (x,y) clause in the SQL statement
                              for (Counter = 0; Counter <= CreateLocationOtherPartnerKeys.Length - 1; Counter += 1)
                              {
                                  OtherPartnerKeys = OtherPartnerKeys + CreateLocationOtherPartnerKeys[Counter].ToString() + ',';
                              }
  
                              // remove last ','
                              OtherPartnerKeys = OtherPartnerKeys.Substring(0, OtherPartnerKeys.Length - 1);
  
                              // Load data for all the other selected Partners that reference
                              // the PartnerLocation
                              PartnerLocationModifyDS = new DataSet();
                              PartnerLocationModifyDS.Tables.Add(new PPartnerLocationTable());
                              ParametersArray = new OdbcParameter[2];
                              ParametersArray[0] = new OdbcParameter("", OdbcType.Decimal, 10);
                              ParametersArray[0].Value = (System.Object)(NewLocationRowSaved.SiteKey);
  
gt:                             ParametersArray[1] = new OdbcParameter("", OdbcType.Int);