/// <summary>
        /// This method sets the value of Reason (ClaimTransactionDescription) as "Claim Detail Closed" and allocates next transaction reference to Claim Transaction Reference (ClaimTransactionHeaderReference) 
        /// if claim detail is being closed and corresponding reserves are being set to zero.  
        /// </summary>
        /// <param name="businessTransaction">Business Transaction</param>
        /// <param name="point">Transaction Point</param>
        /// <param name="PluginId">Plugin Id</param>
        /// <param name="parameters">Extra Parameters</param>
        /// <returns>Process Results Collection</returns>
        public ProcessResultsCollection ProcessTransaction(Xiap.Framework.BusinessTransaction.IBusinessTransaction businessTransaction, TransactionInvocationPoint point, int PluginId, params object[] parameters)
        {
            if (point == TransactionInvocationPoint.PreComplete)
            {
                ClaimHeader claimHeader = (ClaimHeader)businessTransaction.Component;
                foreach (var inProgressTransactionHeader in claimHeader.InProgressClaimTransactionHeaders)
                {
                    if (inProgressTransactionHeader.ClaimTransactionSource == (short)StaticValues.ClaimTransactionSource.Reserve || inProgressTransactionHeader.ClaimTransactionSource == (short)StaticValues.ClaimTransactionSource.RecoveryReserve)
                    {
                        foreach (var ctg in inProgressTransactionHeader.ClaimTransactionGroups)
                        {
                            ClaimDetail claimDetail = ctg.ClaimDetail;
                            if (claimDetail.OriginalTransitionStatus != claimDetail.ClaimDetailStatusCode)
                            {
                                // if ClaimDetail is being closed or finalized
                                if (claimDetail.ClaimDetailInternalStatus == (short?)StaticValues.ClaimDetailInternalStatus.ClosedCreatedinError ||
                                    claimDetail.ClaimDetailInternalStatus == (short?)StaticValues.ClaimDetailInternalStatus.Finalized)
                                {
                                    // if finalization is allowed with non-zero Outstanding
                                    if (claimDetail.GetProduct().IsFinalizationWithNonZeroOSAllowed.GetValueOrDefault(false))
                                    {
                                        inProgressTransactionHeader.ClaimTransactionDescription = "Claim Detail Closed";
                                        inProgressTransactionHeader.ClaimTransactionHeaderReference = LockManager.AllocateReference(string.Empty, ReferenceType.ClaimTransactionHeaderReference, string.Empty, "0000000001", 10, "9999999999", false);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return businessTransaction.Results;
        }
        private const string GenericDataType_Deductible_Service = "GenericDataType.Deductible.Service"; // SVC

        #region ITransactionPlugin Members

        /// <summary>
        /// Processes the transaction - validates policy data items on PostValidate
        /// </summary>
        /// <param name="businessTransaction">The business transaction.</param>
        /// <param name="point">The point.</param>
        /// <param name="PluginId">The plugin identifier.</param>
        /// <param name="parameters">The parameters.</param>
        /// <returns>Process Results Collection or null</returns>
        public ProcessResultsCollection ProcessTransaction(IBusinessTransaction businessTransaction, TransactionInvocationPoint point, int PluginId, params object[] parameters)
        {
            if (point == TransactionInvocationPoint.PostValidate)
            {
                return this.ValidatePolicyDataItems((Header)businessTransaction.Component);
            }

            return null;
        }
        /// <summary>
        /// Adds error details to the transaction if the payment cannot be cancelled because unauthorised reserves,
        /// payments, or recovery receipts still exist on it.
        /// invoked when CancelPayment transaction is selected. 
        /// </summary>
        /// <param name="businessTransaction">TransactionType CancelPayment</param>
        /// <param name="point">Pre Create</param>
        /// <param name="PluginId">Plug ID</param>
        /// <param name="parameters">Process Transaction Parameters</param>
        /// <returns>return Result Collection</returns>
        public ProcessResultsCollection ProcessTransaction(IBusinessTransaction businessTransaction, TransactionInvocationPoint point, int PluginId, params object[] parameters)
        {
            if (point == TransactionInvocationPoint.PreCreate)
            {
                PreValidate(businessTransaction);
            }

            return businessTransaction.Results;
        }
        /// <summary>
        /// Transaction process started on Pre complete invocation point.
        /// </summary>
        /// <param name="businessTransaction">transaction of Business Type</param>
        /// <param name="point">Process Invocation Point</param>
        /// <param name="PluginId">unique plugin id</param>
        /// <param name="parameters">Process parameters</param>
        /// <returns>collection of process results</returns>
        public ProcessResultsCollection ProcessTransaction(IBusinessTransaction businessTransaction, TransactionInvocationPoint point, int PluginId, params object[] parameters)
        {
            if (point == TransactionInvocationPoint.PreComplete)
            {
                ClaimHeader claimHeader = (ClaimHeader)businessTransaction.Component;

                // If ClaimHeaderStatusCode is "Report Only-No Estimates" or "Report Only-Estimates Made" 
                // then raise errors if there are any payments or recovery receipts in progress
                if (claimHeader.ClaimHeaderStatusCode == "CRO" || claimHeader.ClaimHeaderStatusCode == "CRE")
                {
                    if (this.InProgressPaymentExists(claimHeader))
                    {
                        Xiap.Claims.BusinessLogic.ClaimsBusinessLogicHelper.AddError(businessTransaction.Results, "ENTRY_NOT_ALLOWED_FOR_REPORT_ONLY_CLAIMS", point, claimHeader, StaticValues.ClaimTransactionSource.Payment);
                    }
                    else if (this.InProgressRecoveryReceiptExists(claimHeader))
                    {
                        Xiap.Claims.BusinessLogic.ClaimsBusinessLogicHelper.AddError(businessTransaction.Results, "ENTRY_NOT_ALLOWED_FOR_REPORT_ONLY_CLAIMS", point, claimHeader, StaticValues.ClaimTransactionSource.RecoveryReceipt);
                    }
                }

                // If ClaimHeaderStatusCode is "Open - Payment Made" or "Open - Estimate Made" or "Open - No Estimate" or "Report Only - No Estimate"
                // then update the header status code based on payments or reserves.
                if (claimHeader.ClaimHeaderStatusCode == "CPY" || claimHeader.ClaimHeaderStatusCode == "CES" || claimHeader.ClaimHeaderStatusCode == "COU" || claimHeader.ClaimHeaderStatusCode == "CRO")
                {
                    // Check for any payments found on the claim.
                    if (this.IsPaymentFoundOnClaimTransactionHeaders(claimHeader))
                    {
                        claimHeader.ClaimHeaderStatusCode = "CPY";// Change to "Open - Payment Made" 
                        claimHeader.PropertiesChanged.Remove(ClaimHeader.ClaimHeaderStatusCodeFieldName);////fix to remove status validation error from ces to cpy                         
                    }                    
                    else if (this.IsReserveFoundOnClaimTransactionHeaders(claimHeader))
                    {
                        // Reserve Made and header status is "Report Only - No Estimate"
                        if (claimHeader.ClaimHeaderStatusCode == "CRO")
                        {
                            claimHeader.ClaimHeaderStatusCode = "CRE"; // change to "Report Only-Estimates Made" 
                        }
                        else
                        {
                            claimHeader.ClaimHeaderStatusCode = "CES"; // else change to "Open - Estimate Made"
                        }
                    }
                    else
                    {
                        // "Report Only - No Estimate"
                        if (claimHeader.ClaimHeaderStatusCode != "CRO")
                        {
                            // change to "Open - No Estimate"
                            claimHeader.ClaimHeaderStatusCode = "COU";
                        }
                    }
                }
            }

            return businessTransaction.Results;
        }
       /// <summary>
       /// Call on ClaimHandlerEventDefaulter.
       /// Generate an event if this is a PreComplete invocation point.
       /// </summary>
       /// <param name="businessTransaction">Claim Header</param>
       /// <param name="point">Point PreComplete</param>
       /// <param name="PlunginId">PlugIn ID</param>
       /// <param name="Paramaters">Processing Transaction Parameters</param>
       /// <returns>return ProcessResultCollection which have Error msg If any validation failed.</returns>
        public ProcessResultsCollection ProcessTransaction(IBusinessTransaction businessTransaction, TransactionInvocationPoint point, int PlunginId, params object[] Paramaters)
        {
            ClaimHeader claimHeader = (ClaimHeader)businessTransaction.Component;
            if (point == TransactionInvocationPoint.PreComplete)
            {
                this.GenerateEvent(claimHeader);
            }

            return businessTransaction.Results;
        }
        /// <summary>
        /// Add Claim wake up Validation
        /// </summary>
        /// <param name="businessTransaction">Bussiness Transaction Reopen Claim</param>
        /// <param name="point">Pre Creat</param>
        /// <param name="PluginId">Plugin Id</param>
        /// <param name="parameters">Extra Parameters</param>
        /// <returns>Process Results Collection</returns>
        public ProcessResultsCollection ProcessTransaction(IBusinessTransaction businessTransaction, TransactionInvocationPoint point, int PluginId, params object[] parameters)
        {
            switch (point)
            {
                case TransactionInvocationPoint.PreCreate:
                    this.ValidateMigrationStatus(businessTransaction, point);
                    break;
            }

            return businessTransaction.Results;
        }
        /// <summary>
        /// Process on Pre-Create of a Genius controlled name usage type.
        /// </summary>
        /// <param name="businessTransaction">The business transaction.</param>
        /// <param name="point">The point.</param>
        /// <param name="PluginId">The plugin identifier.</param>
        /// <param name="parameters">The parameters.</param>
        /// <returns>Process Results Collection</returns>
        public ProcessResultsCollection ProcessTransaction(IBusinessTransaction businessTransaction, TransactionInvocationPoint point, int PluginId, params object[] parameters)
        {
            if (point == TransactionInvocationPoint.PreCreate)
            {
                Name sourceName = businessTransaction.Component as Name;
                if (sourceName.NameUsages.Any(nu=>nu.GetDefinitionComponent().CustomCode01 != IDConstants.NAME_CONTROLLED_IN_GENIUSX))
                {
                    // This will throw an exception of the user isn't allowed to maintain Genius-controlled names.
                    InsuranceDirectoryBusinessLogicHelper.VerifyPermissionForCurrentUser(IDConstants.GENIUS_SOURCED_NAME_MAINTENANCE_PERMISSION_TOKEN);
                }
            }

            return businessTransaction.Results;
        }
        /// <summary>
        /// Call on ClaimEventTransaction
        /// </summary>
        /// <param name="businessTransaction">Event Container</param>
        /// <param name="point">Point such as PostComplete,PreComplete </param>
        /// <param name="PluginId">PlugIN ID</param>
        /// <param name="parameters">Processing Trasnaction Parameters</param>
        /// <returns>return ProcessResultCollection which have Error msg If any validation failed.</returns>
        public ProcessResultsCollection ProcessTransaction(IBusinessTransaction businessTransaction, TransactionInvocationPoint point, int PluginId, params object[] parameters)
        {
            try
            {
                // If Transaction Invocation Point is 'PostComplete' or 'PreComplete', then check if the ClaimHeaderStatusCode has changed and trigger the 
                // corresponding virtual 'Process-handler' plug-ins
                if (point == TransactionInvocationPoint.PostComplete || point == TransactionInvocationPoint.PreComplete)
                {
                    IEventContainer eventContainer;
                    // Get the event container, either from the component or its parent.
                    if (businessTransaction.Component is IEventContainer)
                    {
                        eventContainer = (IEventContainer)businessTransaction.Component;
                    }
                    else
                    {
                        eventContainer = (IEventContainer)businessTransaction.Component.Parent;
                    }

                    if (point == TransactionInvocationPoint.PreComplete)
                    {
                        // Create event(s) based on the sources (Payment, Reserve, Recoveries) on the Claim Transaction Header
                        this.CreateEventOnTransaction(eventContainer);
                    }

                    // Check Newly added event and invoke the process handler if attached with the event.
                    foreach (IEvent ev in eventContainer.Events)
                    {
                        if (ev.IsNew)
                        {
                            this.InvokeVirtualProcess(ev, eventContainer, point);
                        }
                    }

                    // Check Deleted event and invoke the process handler if attached with the event.
                    foreach (IEvent ev in businessTransaction.Context.DeletedEvents)
                    {
                        this.InvokeVirtualProcess(ev, eventContainer, point);
                    }
                }
            }
            catch (Exception e)
            {
                _Logger.Error(e);
                throw;
            }

            return businessTransaction.Results;
        }
        /// <summary>
        /// Check whether migration processing has been completed or not.
        /// </summary>
        /// <param name="businessTransaction">IBusiness Transaction</param>
        /// <param name="point">Transaction Invocation Point</param>
        private void ValidateMigrationStatus(IBusinessTransaction businessTransaction, TransactionInvocationPoint point)
        {
            ClaimHeader claimHeader = (ClaimHeader)businessTransaction.Component;

            // UI Label = Data Source
            if (claimHeader.CustomCode19 == ClaimConstants.CLAIMS_MIGRATION_STATUS)   
            {
                // ClaimWakeUp Validations
                // CustomCode18=CMS Migration Status
                // UI Label = CMS Migration Status
                // if REOPENING OF UNPROCESSED CLAIM NOT ALLOWED
                // else if MIGRATED CLOSED CLAIM BEING PROCESSED
                // send message REOPENING OF A CLAIM ALREADY BEING PROCESSED NOT ALLOWED
                // else if = FAILED DUE TO INTERNAL SERVICE CONNECTION ISSUES
                // send message REOPENING OF A CLAIM THAT FAILED PROCESSING NOT ALLOWED
                // else if FAILED POLICY DOES NOT EXIST IN GENIUSX
                // send message REOPENING OF A CLAIM NOT ALLOWED WITHOUT POLICY
                // else if FAILED POLICY EXISTS BUT COULD NOT ATTACH TO CLAIM
                // send message REOPENING OF CLAIM NOT ALLOWED POLICY FAILURE

                if (string.IsNullOrWhiteSpace(claimHeader.CustomCode18))   
                {
                    ClaimsBusinessLogicHelper.AddFatalError(businessTransaction.Results, ClaimConstants.REOPENING_OF_UNPROCESSED_CLAIM_NOT_ALLOWED,point, businessTransaction.Component);
                }
                else if (claimHeader.CustomCode18 == ClaimConstants.MIGRATED_CLOSED_CLAIM_BEING_PROCESSED)   
                {
                    ClaimsBusinessLogicHelper.AddFatalError(businessTransaction.Results, ClaimConstants.REOPENING_OF_A_CLAIM_ALREADY_BEING_PROCESSED_NOT_ALLOWED, point, businessTransaction.Component);
                }
                else if (claimHeader.CustomCode18 == ClaimConstants.FAILED_DUE_TO_INTERNAL_SERVICE_CONNECTION_ISSUES)   
                {
                    ClaimsBusinessLogicHelper.AddFatalError(businessTransaction.Results, ClaimConstants.REOPENING_OF_A_CLAIM_THAT_FAILED_PROCESSING_NOT_ALLOWED, point, businessTransaction.Component);
                }
                else if (claimHeader.CustomCode18 == ClaimConstants.FAILED_POLICY_DOES_NOT_EXIST_IN_GENIUSX)   
                {
                    ClaimsBusinessLogicHelper.AddFatalError(businessTransaction.Results, ClaimConstants.REOPENING_OF_CLAIM_NOT_ALLOWED_WITHOUT_POLICY, point, businessTransaction.Component);
                }
                else if (claimHeader.CustomCode18 == ClaimConstants.FAILED_POLICY_EXISTS_BUT_COULD_NOT_ATTACH_TO_CLAIM)   
                {
                    ClaimsBusinessLogicHelper.AddFatalError(businessTransaction.Results, ClaimConstants.REOPENING_OF_CLAIM_NOT_ALLOWED_POLICY_FAILURE, point, businessTransaction.Component);
                }
            }
        }
        /// <summary>
        /// Process on the PostComplete point.
        /// If Create Claim,CloseClaim,ReopenClaim,AmendClaim,Copy,Delete ,CancelPayment,ReserveAuthorisation,PaymentAuthorisation,RecoveryReceiptAuthorisation
        /// </summary>
        /// <param name="businessTransaction">Processing ClaimTransactionHeader</param>
        /// <param name="point">it is invocation(PostComplete)</param>
        /// <param name="PluginId">Plugin ID</param>
        /// <param name="parameters">Process transaction Parameters if any </param>
        /// <returns>return Result Collection</returns>
        public ProcessResultsCollection ProcessTransaction(IBusinessTransaction businessTransaction, TransactionInvocationPoint point, int PluginId, params object[] parameters)
        {
            ClaimHeader claimHeader = null;
            using (PerfLogger _LG = new PerfLogger(typeof(AXAClaimTransferPlugin), "AXAClaimTransferPlugin"))
            {
                if (point == TransactionInvocationPoint.PostComplete)
                {
                    if (businessTransaction.Component != null)
                    {
                        if (businessTransaction.Component is ClaimTransactionHeader)
                        {
                            claimHeader = businessTransaction.Component.Parent as ClaimHeader;
                        }
                        else
                        {
                            claimHeader = businessTransaction.Component as ClaimHeader;
                        }
                    }

                    // Get invalid Header Status codes from the application configuration
                    // No claims of this header status code will be transferred.
                    string invalidClaimHeaderStatusCodes = ClaimsBusinessLogicHelper.ResolveMandatoryConfig<string>(ClaimConstants.APP_SETTING_KEY_HEADERSTATUSESFORINVALIDCLAIMTRANSFER);
                    if (claimHeader != null && ClaimsBusinessLogicHelper.CheckValidHeaderStatus(claimHeader, invalidClaimHeaderStatusCodes))
                    {
                        if (_Logger.IsDebugEnabled)
                        {
                            _Logger.Debug(claimHeader.ClaimReference + " : has valid claim header status code.");
                        }

                        // If header status of claim has been changed to Abandoned then if previous header status was valid then insert entry in claim transfer control log table.
                        if (claimHeader.ClaimHeaderStatusCode == ClaimConstants.CLAIM_HEADER_STATUS_ABANDONED)
                        {
                            if (claimHeader.OriginalTransitionStatus == ClaimConstants.CLAIM_HEADER_STATUS_NO_ESTIMATE
                                || claimHeader.OriginalTransitionStatus == ClaimConstants.CLAIM_HEADER_STATUS_ESTIMATE_MADE
                                || claimHeader.OriginalTransitionStatus == ClaimConstants.CLAIM_HEADER_STATUS_PAYMENT_MADE)
                            {
                                this.AddClaimTransferControlLogEntry(businessTransaction);
                            }

                            // No further processing of an abandoned claim
                            return null;
                        }

                        // Check if status is moved from invalid to valid then write out all ClaimTransactions to Transfer log which were added when claim status was invalid.
                        List<string> invalidClaimHeaderStatusesList = invalidClaimHeaderStatusCodes.Split(',').ToList<string>();
                        if (!string.IsNullOrEmpty(invalidClaimHeaderStatusCodes)
                            && claimHeader.OriginalTransitionStatus != claimHeader.ClaimHeaderStatusCode
                            && invalidClaimHeaderStatusesList.Contains(claimHeader.OriginalTransitionStatus.ToString())
                            && !invalidClaimHeaderStatusesList.Contains(claimHeader.ClaimHeaderStatusCode.ToString()))
                        {
                            // If there is status transition from invalid to valid then this won't insert records for financial transactions instead 
                            // Stored Procedure will insert all the finanical transactions.
                            this.AddClaimTransferControlLogEntry(businessTransaction, false);
                            if (_Logger.IsDebugEnabled)
                            {
                                _Logger.Debug(claimHeader.ClaimReference + " : Using SP to to Inserting financial records that were made when claim was having invalid header status code into ClaimTransferControlLog table.");
                            }

                            // Use Stored Procedure to retroactively insert the necessary financial recors.
                            IAXAClaimsQuery query = ObjectFactory.Resolve<IAXAClaimsQuery>();
                            query.ExecuteClaimTransferControlLogSP(claimHeader.ClaimReference.ToString());
                        }
                        else
                        {
                            if (_Logger.IsDebugEnabled)
                            {
                                _Logger.Debug(claimHeader.ClaimReference + " : Inserting financial records of claim having valid header status code, into ClaimTransferControlLog table.");
                            }

                            // This will insert records for create/update claim and financial transaction if exist.
                            this.AddClaimTransferControlLogEntry(businessTransaction, true);
                        }
                    }
                }
            }

            return null;
        }