/// <summary>
        /// Load historical reserves/payments/recovery reserves/recovery receipts for the specified claim
        /// </summary>
        /// <param name="transactionSource">transaction source</param>
        /// <param name="productClaimDefinition">claim product</param>
        /// <param name="claimDetailProductMap">claim details used for filtering</param>
        /// <param name="claimHeader">claim header</param>
        /// <param name="reserves">resulting reserves</param>
        /// <param name="payments">resulting payments and recovery receipts</param>
        /// <param name="recoveryReserves">resulting recovery reserves</param>
        private static void LoadFinancialAmounts(StaticValues.ClaimTransactionSource transactionSource, ProductClaimDefinition productClaimDefinition, IDictionary<string, ProductClaimDetail> claimDetailProductMap, ClaimHeader claimHeader, ClaimTransactionHeader claimtransactionheader, out IEnumerable<ClaimFinancialAmount> reserves, out IEnumerable<ClaimFinancialAmount> payments, out IEnumerable<ClaimFinancialAmount> recoveryReserves)
        {
            var inProgressData = ObjectFactory.Resolve<IInProgressFinancialAmountData>();
            var historicalData = ObjectFactory.Resolve<IHistoricalFinancialAmountData>();

            var claimHeaderArg = new ClaimHeaderArgument(AmountDataSource.Both, claimHeader, claimtransactionheader);

            var validClaimDetails = claimDetailProductMap
                .Where(a => a.Value.ClaimDetailAutomaticDeductibleProcessingMethod == (short)StaticValues.ClaimDetailAutomaticDeductibleProcessingMethod.FromClaimHeader)
                .Select(a => a.Key);

            var reserveCalculation = new TotalClaimReserveFinancialCalculation(inProgressData, historicalData);
            var paymentCalcuation = new TotalClaimPaymentFinancialCalculation(inProgressData, historicalData);
            var recoveryReceiptCalculation = new TotalClaimReceiptFinancialCalculation(inProgressData, historicalData);
            var recoveryRerserveCalculation = new TotalClaimRecoveryReserveFinancialCalculation(inProgressData, historicalData);
            bool includeEstimated = productClaimDefinition.IncurredAmountDerivationMethod == (short)StaticValues.IncurredAmountDerivationMethod.PaymentsReservesincludingEstimated;
            bool includeRecoveryEstimated = productClaimDefinition.RecoveryIncurredAmountDerivationMethod == (short)StaticValues.RecoveryIncurredAmountDerivationMethod.ReceiptsRecoveryReservesincludingEstimated;
            reserves = reserveCalculation.ReadLatestClaimReserves(claimHeaderArg, includeEstimated).Where(a => validClaimDetails.Contains(a.ClaimDetailReference));
            payments = paymentCalcuation.ReadClaimPayments(claimHeaderArg).Where(a => validClaimDetails.Contains(a.ClaimDetailReference));
            payments = payments.Concat(recoveryReceiptCalculation.ReadClaimReceipts(claimHeaderArg).Where(a => validClaimDetails.Contains(a.ClaimDetailReference)));
            recoveryReserves = recoveryRerserveCalculation.ReadLatestClaimRecoveryReserves(claimHeaderArg, includeRecoveryEstimated).Where(a => validClaimDetails.Contains(a.ClaimDetailReference));


            var excludedMovementTypes = ClaimsBusinessLogicHelper.GetExcludedMovementTypesFromAutomaticDeductibleCalculations();
            reserves = FilterExcludedMovementTypes(reserves, excludedMovementTypes);
            recoveryReserves = FilterExcludedMovementTypes(recoveryReserves, excludedMovementTypes);
            payments = FilterExcludedMovementTypes(payments, excludedMovementTypes);

            reserves = CreateAmountsForCalculation(reserves);
            recoveryReserves = CreateAmountsForCalculation(recoveryReserves);
            payments = CreateAmountsForCalculation(payments);
        }
        /// <summary>
        /// Load historical reserves/payments/recovery reserves/recovery receipts for the specified claim detail
        /// </summary>
        /// <param name="transactionSource">transaction source</param>
        /// <param name="productClaimDefinition">claim product</param>
        /// <param name="claimDetail">claim detail</param>
        /// <param name="reserves">resulting reserves</param>
        /// <param name="payments">resulting payments and recovery receipts</param>
        /// <param name="recoveryReserves">resulting recovery reserves</param>
        private static void LoadFinancialAmounts(StaticValues.ClaimTransactionSource transactionSource, ProductClaimDefinition productClaimDefinition, ClaimDetail claimDetail, ClaimTransactionHeader claimtransactionheader, out IEnumerable<ClaimFinancialAmount> reserves, out IEnumerable<ClaimFinancialAmount> payments, out IEnumerable<ClaimFinancialAmount> recoveryReserves)
        {
            var inProgressData = ObjectFactory.Resolve<IInProgressFinancialAmountData>();
            var historicalData = ObjectFactory.Resolve<IHistoricalFinancialAmountData>();

            var claimDetailArg = new ClaimDetailArgument(AmountDataSource.Both, claimDetail, null);

            var reserveCalculation = new TotalClaimDetailReserveFinancialCalculation(inProgressData, historicalData);
            var paymentCalcuation = new TotalClaimDetailPaymentFinancialCalculation(inProgressData, historicalData);
            var recoveryReceiptCalculation = new TotalClaimDetailReceiptFinancialCalculation(inProgressData, historicalData);
            var recoveryRerserveCalculation = new TotalClaimDetailRecoveryReserveFinancialCalculation(inProgressData, historicalData);
            bool includeEstimated = productClaimDefinition.RecoveryIncurredAmountDerivationMethod == (short)StaticValues.RecoveryIncurredAmountDerivationMethod.ReceiptsRecoveryReservesincludingEstimated;
            bool includeRecoveryEstimated = productClaimDefinition.RecoveryIncurredAmountDerivationMethod == (short)StaticValues.RecoveryIncurredAmountDerivationMethod.ReceiptsRecoveryReservesincludingEstimated;
            reserves = reserveCalculation.ReadLatestClaimDetailReserves(claimDetailArg, includeEstimated);
            payments = paymentCalcuation.ReadClaimDetailPayments(claimDetailArg);
            payments = payments.Concat(recoveryReceiptCalculation.ReadClaimDetailReceipt(claimDetailArg));
            recoveryReserves = recoveryRerserveCalculation.ReadLatestClaimDetailRecoveryReserves(claimDetailArg, includeRecoveryEstimated);

            var excludedMovementTypes = ClaimsBusinessLogicHelper.GetExcludedMovementTypesFromAutomaticDeductibleCalculations();
            reserves = FilterExcludedMovementTypes(reserves, excludedMovementTypes);
            recoveryReserves = FilterExcludedMovementTypes(recoveryReserves, excludedMovementTypes);
            payments = FilterExcludedMovementTypes(payments, excludedMovementTypes);

            reserves = CreateAmountsForCalculation(reserves);
            recoveryReserves = CreateAmountsForCalculation(recoveryReserves);
            payments = CreateAmountsForCalculation(payments);
        }
 private static bool IsCalculatingDeductibles(ProductClaimDetail productClaimDetail, ProductClaimDefinition productClaimDefinition, ClaimHeader claimHeader)
 {
     return productClaimDetail.ClaimDetailAutomaticDeductibleProcessingMethod == (short)StaticValues.ClaimDetailAutomaticDeductibleProcessingMethod.FromClaimHeader
         && productClaimDefinition.ClaimHeaderAutomaticDeductibleProcessingMethod == (short)StaticValues.ClaimHeaderAutomaticDeductibleProcessingMethod.StandardClaimHeaderDeductible
         && claimHeader.IsAutomaticDeductibleProcessingApplied == true;
 }
        private static decimal CalculateTotalIncurred(ProductClaimDefinition productClaimDefinition, decimal totalPaid, IEnumerable<ClaimFinancialAmount> reserves)
        {
            if (productClaimDefinition.IncurredAmountDerivationMethod != (short)StaticValues.IncurredAmountDerivationMethod.PaymentsOnly)
            {
                totalPaid += reserves.Sum(a => a.TransactionAmountClaimCurrency.GetValueOrDefault(0));
            }

            return totalPaid;
        }
        /// <summary>
        /// For each deductible associated with this transaction we need to calculate how the latest transaction has affected the the current deductibles and generate any new deductibles as required
        /// </summary>
        /// <param name="productClaimDefinition">calim product</param>
        /// <param name="financialContext">context variables</param>
        /// <param name="deductibleDefinitions">deductibles associated with this transaction</param>
        /// <param name="reserves">historical reserves</param>
        /// <param name="payments">historical payments</param>
        /// <param name="recoveryReserves">recovery reserves</param>
        /// <returns>Deductible Result</returns>
        private static DeductibleResult CalculateDeductibles(ProductClaimDefinition productClaimDefinition, FinancialTransactionContext financialContext, IEnumerable<DeductibleDefinition> deductibleDefinitions, IEnumerable<ClaimFinancialAmount> reserves, IEnumerable<ClaimFinancialAmount> payments, IEnumerable<ClaimFinancialAmount> recoveryReserves)
        {
            var deductibleResult = new DeductibleResult { Success = true };
            var deductibleMovementTypes = deductibleDefinitions.SelectMany(a => a.GetMovementTypes());
            var recoveryDeductibleMovementTypes = deductibleDefinitions.SelectMany(a => a.GetRecoveryMovementTypes());


            var claimDetailRefs = financialContext.ClaimHeader.ClaimDetails.Select(a => a.ClaimDetailReference);
            var deductibleReserveContext = new DeductibleReserveCapacity(claimDetailRefs, reserves, deductibleMovementTypes);
            var deductibleRecoveryReserveContext = new DeductibleReserveCapacity(claimDetailRefs, recoveryReserves, recoveryDeductibleMovementTypes);

            bool isRecovery = IsRecovery(financialContext.TransactionSource);
            decimal sumOfLowerDeductibles = 0;
            decimal totalPaid = payments.Where(a => !deductibleMovementTypes.Contains(a.MovementType)).Sum(a => a.TransactionAmountClaimCurrency.GetValueOrDefault());
            decimal totalIncurred = CalculateTotalIncurred(productClaimDefinition, totalPaid, reserves.Where(a => !deductibleMovementTypes.Contains(a.MovementType)));
            decimal totalRecoveryIncurred = totalIncurred + recoveryReserves.Where(a => !recoveryDeductibleMovementTypes.Contains(a.MovementType)).Sum(a => a.TransactionAmountClaimCurrency.GetValueOrDefault(0));


            foreach (var deductible in deductibleDefinitions)
            {
                decimal deductiblePaid = CalculateDeductiblePayment(deductible, totalPaid, sumOfLowerDeductibles, payments);
                if (deductiblePaid != 0)
                {
                    var amountType = isRecovery ? StaticValues.AmountType.RecoveryReceipt : StaticValues.AmountType.Payment;
                    AddClaimTransactionDetails(financialContext.ClaimTransactionHeader.TransactionDate.GetValueOrDefault(DateTime.MinValue), financialContext.ClaimTransactionGroup, amountType, deductible, deductiblePaid);
                }

                if (isRecovery && deductible.RecoveryNonFundedMovementType != null)
                {
                    ClaimFinancialAmount latestReserve = LatestReserveOrNull(recoveryReserves, financialContext, deductible.RecoveryNonFundedMovementType);
                    decimal deductibleRecoveryReserve = CalculateDeductibleRecoveryReserves(deductible, latestReserve, totalIncurred, totalRecoveryIncurred, sumOfLowerDeductibles, recoveryReserves);
                    // although a deductible recovery reserve is a negative amount we want to keep it as a positive for now so we can apply deductible reserve adjustments
                    deductibleRecoveryReserve = -deductibleRecoveryReserve;
                    var reserveAdjResult = ApplyDeductibleReserveAdjustments(deductible.RecoveryNonFundedMovementType, deductible, deductibleRecoveryReserveContext, financialContext, recoveryReserves, latestReserve, deductibleRecoveryReserve);
                    deductibleRecoveryReserveContext.AppendToLowerDeductibles(deductible.RecoveryNonFundedMovementType);

                    if (!reserveAdjResult.Success)
                    {
                        deductibleResult = reserveAdjResult;
                    }
                }

                if (financialContext.TransactionSource != StaticValues.ClaimTransactionSource.RecoveryReserve)
                {
                    ClaimFinancialAmount latestReserve = LatestReserveOrNull(reserves, financialContext, deductible.NonFundedMovementType);
                    decimal deductibleReserve = CalculateDeductibleReserves(deductible, latestReserve, totalPaid, totalIncurred, sumOfLowerDeductibles, reserves);
                    var reserveAdjResult = ApplyDeductibleReserveAdjustments(deductible.NonFundedMovementType, deductible, deductibleReserveContext, financialContext, reserves, latestReserve, deductibleReserve);
                    deductibleReserveContext.AppendToLowerDeductibles(deductible.NonFundedMovementType);

                    if (!reserveAdjResult.Success)
                    {
                        deductibleResult = reserveAdjResult;
                    }
                }



                sumOfLowerDeductibles += deductible.Amount;
            }

            return deductibleResult;
        }
        public void Initialise()
        {
            var container = new UnityContainer();

            this.RegisterAuthorityChecks(container);

            var claimTransaction = new BusinessComponentBuilder<ClaimTransactionHeader>();

            this.currentUser = CreateUser("CurrenUserIdentity", 1, 10);
            this.targetUser1 = CreateUser("TargetUser1Identity", 2, 10);
            this.targetUser2 = CreateUser("TargetUser2Identity", 3, 0);

            var componentMetadata = MockRepository.GenerateStub<IComponentMetadata>();
            container.RegisterInstance<IComponentMetadata>(componentMetadata);
            var product = new ProductBuilder<ProductVersion>(componentMetadata)
                            .SetProperty(a => a.GradeStructureType = GradeStructureCode) 
                            .Add(new ProductBuilder<ProductClaimDefinition>(componentMetadata)
                                .SetProperty(a => a.IsManualAuthorisationAlwaysAllowedIfNoChecksAreActive = true))
                         .Build();

            this.productClaimDefinition = product.ProductClaimDefinition;

            ObjectFactory.Instance = new ObjectFactory(container);

            var clmHeader = new BusinessComponentBuilder<ClaimHeader>()
                      .Add(new BusinessComponentBuilder<ClaimDetail>()
                      .As(out claimDetailRef)
                       .SetProperty(a => a.PolicyLinkLevel = (short)StaticValues.PolicyLinkLevel.Header)
                       .SetProperty(a => a.ProductClaimDetailID = 1)
                       .SetProperty(a => a.ClaimDetailReference = "Claim Detail Reference"))
                      .Add(new BusinessComponentBuilder<ClaimTransactionHeader>()
                        .SetProperty(a => a.IsInProgress = true)
                        .Add(new BusinessComponentBuilder<ClaimTransactionGroup>()
                            .AddRef(claimDetailRef)
                            .SetProperty(a => a.AdministerClaimMethod = 2)))
                  .Build();

            clmHeader.ClaimHeaderAnalysisCode01 = ClaimConstants.CH_ANALYSISCODE_MOTOR;

            this.claimHeader = clmHeader;
            var claimsEntities = MockRepository.GenerateStub<IClaimsQuery>();
            claimsEntities.Stub(a => a.GetClaimTransactionHeader(0)).IgnoreArguments().Return(this.claimHeader.InProgressClaimTransactionHeaders.Single());
            container.RegisterInstance<IClaimsQuery>(claimsEntities);

            this.gradesforStructure = new List<Grade> { CreateGrade(GradeCode2, 3), CreateGrade(GradeCode1, 1) };
            this.usersForGradeCode1 = new List<User> { this.currentUser, this.targetUser1 };
            this.usersForGradeCode2 = new List<User>();
            this.eventDestinations = new List<IEventDestination> { CreateEventDestination(this.targetUser1.UserIdentity, "1"), CreateEventDestination(this.targetUser1.UserIdentity, "2") };

            this.metadataEntities = MockRepository.GenerateStub<IMetadataQuery>();
            this.metadataEntities.Stub(a => a.GetUserIdByUserIdentity(this.currentUser.UserIdentity)).Return(this.currentUser.UserID);
            this.metadataEntities.Stub(a => a.GetUserGradeCode(this.currentUser.UserID, GradeStructureCode, StaticValues.GradeType.Claims)).Do(new Func<long, string, StaticValues.GradeType, string>((x, y, z) => this.userGradeCode));
            this.metadataEntities.Stub(a => a.GetGradesForGradeStructure(GradeStructureCode)).Return(this.gradesforStructure);
            this.metadataEntities.Stub(a => a.GetUsersByGradeCode(GradeCode1)).Return(this.usersForGradeCode1);
            this.metadataEntities.Stub(a => a.GetUsersByGradeCode(GradeCode2)).Return(this.usersForGradeCode2);
            container.RegisterInstance(this.metadataEntities);

            var taskService = MockRepository.GenerateStub<ITaskService>();
            taskService.Stub(a => a.GetActiveEventDestinations(null, null, DateTime.Now, DateTime.Now)).IgnoreArguments().Return(this.eventDestinations);
            taskService.Stub(a => a.GetFinishedEventDestinationByDateRange(null, null, DateTime.Now, DateTime.Now)).IgnoreArguments().Return(this.eventDestinations);
            container.RegisterInstance(taskService);


            IAXAClaimsQuery claimsQuery = MockRepository.GenerateStub<IAXAClaimsQuery>();
            claimsQuery.Stub(s => s.IsUserOutOfOffice(Arg<long>.Is.Anything, out Arg<string>.Out(String.Empty).Dummy)).Return(false);
            container.RegisterInstance<IAXAClaimsQuery>(claimsQuery);

            this.businessSupportRole = ClaimsBusinessLogicHelper.ResolveMandatoryConfig<string>("BusinessSupportRole");
        }
        /// <summary>
        /// method used to get funded deductible movement types from the Metadata.
        /// </summary>
        /// <param name="entities">Metadata Entity value</param>
        /// <param name="productVersion">long value</param>
        /// <param name="attachedPolicyRef">string value</param>
        /// <param name="fundedDeductiblePolicies">Dictionary collection</param>
        /// <param name="pcd">Product Claim Definition Type</param>
        /// <param name="recoveryReserveMovementType">string value</param>
        /// <param name="reserveMovementType">string value</param>
        /// <param name="isRecoveryReserve">bool value</param>
        /// <param name="movementTypes">Dictionary collection - Passed by reference</param>
        /// <returns>Dictionary collection</returns>
        private static Dictionary<string, string> GetFundedDeductibleMovementTypes(MetadataEntities entities, long productVersion, string attachedPolicyRef, Dictionary<string, string> fundedDeductiblePolicies, ProductClaimDefinition pcd, string recoveryReserveMovementType, string reserveMovementType, bool isRecoveryReserve, ref Dictionary<string, string> movementTypes)
		{
			if (_Logger.IsInfoEnabled)
			{
				_Logger.Info("ClaimTransferDataCollection.GetFundedDeductibleMovementTypes");
			}

            // For each of the five Deductible codes, check if we are adding to the list of Dedctible moment type codes.
            AddDeductibleMovemnentTypeCodes(ClaimConstants.DED_DEDUCTIBLE01, pcd.InsurerFundedDeductible01MovementTypeCode, attachedPolicyRef, fundedDeductiblePolicies, recoveryReserveMovementType, reserveMovementType, isRecoveryReserve, ref movementTypes);
            AddDeductibleMovemnentTypeCodes(ClaimConstants.DED_DEDUCTIBLE02, pcd.InsurerFundedDeductible02MovementTypeCode, attachedPolicyRef, fundedDeductiblePolicies, recoveryReserveMovementType, reserveMovementType, isRecoveryReserve, ref movementTypes);
            AddDeductibleMovemnentTypeCodes(ClaimConstants.DED_DEDUCTIBLE03, pcd.InsurerFundedDeductible03MovementTypeCode, attachedPolicyRef, fundedDeductiblePolicies, recoveryReserveMovementType, reserveMovementType, isRecoveryReserve, ref movementTypes);
            AddDeductibleMovemnentTypeCodes(ClaimConstants.DED_DEDUCTIBLE04, pcd.InsurerFundedDeductible04MovementTypeCode, attachedPolicyRef, fundedDeductiblePolicies, recoveryReserveMovementType, reserveMovementType, isRecoveryReserve, ref movementTypes);
            AddDeductibleMovemnentTypeCodes(ClaimConstants.DED_DEDUCTIBLE05, pcd.InsurerFundedDeductible05MovementTypeCode, attachedPolicyRef, fundedDeductiblePolicies, recoveryReserveMovementType, reserveMovementType, isRecoveryReserve, ref movementTypes);

			return movementTypes;
		}