/// <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;
        }