private string FindPriceEpisodeIdentifier(decimal value, Earning earning, FM36Learner fm36Learner, TransactionType transactionType) { // null for 0 values if (value == 0) { return(null); } // it could be specified in earnings table if (earning.PriceEpisodeIdentifier != null) { return(earning.PriceEpisodeIdentifier); } // find first price episode with non-zero value for a period var period = earning.DeliveryCalendarPeriod; earning.PriceEpisodeIdentifier = fm36Learner.PriceEpisodes .SingleOrDefault(pe => pe.PriceEpisodePeriodisedValues .Any(pepv => pepv.GetValue(period).GetValueOrDefault(0) != 0 && pepv.AttributeName == transactionType.ToAttributeName()))? .PriceEpisodeIdentifier; return(earning.PriceEpisodeIdentifier); }
public void SetUp() { mocker = AutoMock.GetStrict(); validatorMock = mocker.Mock <ILearnerValidator>(); actBuilder = mocker.Mock <IApprenticeshipContractTypeEarningsEventBuilder>(); functionalSkillBuilder = mocker.Mock <IFunctionalSkillEarningsEventBuilder>(); validatorMock = mocker.Mock <ILearnerValidator>(); configurationHelper = mocker.Mock <IConfigurationHelper>(); configurationHelper .Setup(x => x.HasSetting("Settings", "DoNotGenerateACT1TransactionType4To16Payments")) .Returns(true); configurationHelper .Setup(x => x.GetSetting("Settings", "DoNotGenerateACT1TransactionType4To16Payments")) .Returns("false"); configurationHelper .Setup(x => x.HasSetting("Settings", "DoNotGenerateACT2Payments")) .Returns(true); configurationHelper .Setup(x => x.GetSetting("Settings", "DoNotGenerateACT2Payments")) .Returns("false"); validatorMock.Setup(x => x.Validate(It.IsAny <FM36Learner>())).Returns(new ValidationResult(new List <ValidationRuleResult>())); learner = new FM36Learner(); }
public void ValidationPassesIfThereAreMultiplePriceEpisodes() { var learner = new FM36Learner { PriceEpisodes = new List <PriceEpisode> { new PriceEpisode { PriceEpisodeIdentifier = "pe-1", PriceEpisodeValues = new PriceEpisodeValues { EpisodeStartDate = DateTime.Today.AddMonths(-2), PriceEpisodePlannedEndDate = DateTime.Today, PriceEpisodeActualEndDate = DateTime.Today.AddDays(-36) } }, new PriceEpisode { PriceEpisodeIdentifier = "pe-2", PriceEpisodeValues = new PriceEpisodeValues { EpisodeStartDate = DateTime.Today.AddDays(-35), PriceEpisodePlannedEndDate = DateTime.Today, } } } }; var rule = new OverlappingPriceEpisodeValidationRule(); var result = rule.IsValid(learner); Assert.IsFalse(result.Failed); }
public void Validation_Fails_If_There_Are_Overlapping_Price_Episodes() { var learner = new FM36Learner { PriceEpisodes = new List <PriceEpisode> { new PriceEpisode { PriceEpisodeIdentifier = "pe-1", PriceEpisodeValues = new PriceEpisodeValues { EpisodeStartDate = DateTime.Today.AddMonths(-2), PriceEpisodePlannedEndDate = DateTime.Today.AddDays(-30), PriceEpisodeActualEndDate = DateTime.Today.AddDays(-30) } }, new PriceEpisode { PriceEpisodeIdentifier = "pe-2", PriceEpisodeValues = new PriceEpisodeValues { EpisodeStartDate = DateTime.Today.AddDays(-35), PriceEpisodePlannedEndDate = DateTime.Today, } } } }; var rule = new OverlappingPriceEpisodeValidationRule(); var result = rule.IsValid(learner); Assert.IsTrue(result.Failed, result.FailureReason); }
public AppsMonthlyPaymentModel BuildModel(ILearner learner, FM36Learner learnerData) { return(new AppsMonthlyPaymentModel() { LearnerReferenceNumber = learner.LearnRefNumber, UniqueLearnerNumber = learner.ULN }); }
public AEC_Learner BuildLearner(FM36Learner fm36Learner, int ukprn, string learnRefNumber) { return(new AEC_Learner { UKPRN = ukprn, LearnRefNumber = learnRefNumber, ULN = fm36Learner.ULN }); }
public void TestAct1EarningIsDetected() { // arrange var fm36Learner = new FM36Learner { PriceEpisodes = new List <PriceEpisode>() { new PriceEpisode { PriceEpisodeIdentifier = "1", PriceEpisodeValues = new PriceEpisodeValues { PriceEpisodeContractType = "Non-Levy Contract", EpisodeStartDate = new DateTime(2018, 8, 6), PriceEpisodeAimSeqNumber = 4 }, PriceEpisodePeriodisedValues = new List <PriceEpisodePeriodisedValues>() } }, LearningDeliveries = new List <LearningDelivery> { new LearningDelivery { AimSeqNumber = 4, LearningDeliveryValues = new LearningDeliveryValues { LearnAimRef = "ld1" } } } }; var processLearnerCommand = new ProcessLearnerCommand { Learner = fm36Learner, CollectionYear = 1819, Ukprn = 12345, JobId = 69, CollectionPeriod = 1, IlrSubmissionDateTime = DateTime.UtcNow, SubmissionDate = DateTime.UtcNow }; var learningAim = new IntermediateLearningAim(processLearnerCommand, fm36Learner.PriceEpisodes, fm36Learner.LearningDeliveries); // act var earningEvent = mapper.Map <IntermediateLearningAim, ApprenticeshipContractType1EarningEvent>(learningAim); // assert earningEvent.PriceEpisodes.Single().Identifier.Should().Be("1"); }
private static ProcessLearnerCommand Build(FM36Learner learner, long jobId, DateTime ilrSubmissionDateTime, short academicYear, int collectionPeriod, long ukprn, string fileName) { return(new ProcessLearnerCommand { JobId = jobId, Learner = learner, RequestTime = DateTimeOffset.UtcNow, IlrSubmissionDateTime = ilrSubmissionDateTime, IlrFileName = fileName, CollectionYear = academicYear, CollectionPeriod = collectionPeriod, Ukprn = ukprn }); }
public void Condense() { var learnerOne = new FM36Learner(); var learnerTwo = new FM36Learner(); var learnerThree = new FM36Learner(); var learnerFour = new FM36Learner(); var learnerFive = new FM36Learner(); var learnerSix = new FM36Learner(); var globalOne = new FM36Global() { Learners = new List <FM36Learner>() { learnerOne, learnerTwo, }, }; var globalTwo = new FM36Global() { Learners = new List <FM36Learner> { learnerThree, learnerFour, }, }; var globalThree = new FM36Global() { Learners = new List <FM36Learner> { learnerFive, learnerSix, }, }; var fundingOutputs = new List <FM36Global>() { globalOne, globalTwo, globalThree, }; var fundingOutput = NewService().Condense(fundingOutputs); fundingOutput.Should().Be(globalOne); fundingOutput.Learners.Should().HaveCount(6); fundingOutput.Learners.Should().Contain(new[] { learnerOne, learnerTwo, learnerThree, learnerFour, learnerFive, learnerSix }); }
public ValidationRuleResult IsValid(FM36Learner learner) { foreach (var priceEpisode in learner.PriceEpisodes) { var overlappingPriceEpisode = learner.PriceEpisodes .Where(pe => pe != priceEpisode) .FirstOrDefault(pe => (priceEpisode.PriceEpisodeValues.PriceEpisodeActualEndDate ?? priceEpisode.PriceEpisodeValues.PriceEpisodePlannedEndDate) > pe.PriceEpisodeValues?.EpisodeStartDate && priceEpisode.PriceEpisodeValues.EpisodeStartDate < (pe.PriceEpisodeValues.PriceEpisodeActualEndDate ?? pe.PriceEpisodeValues?.PriceEpisodePlannedEndDate)); if (overlappingPriceEpisode != null) { return(ValidationRuleResult.Failure($"Found overlapping price episodes. Price Episode {priceEpisode.PriceEpisodeIdentifier} overlapped with price episode {overlappingPriceEpisode.PriceEpisodeIdentifier}.")); } } return(ValidationRuleResult.Ok()); }
protected IntermediateLearningAim( FM36Learner learner, LearningDelivery aim, IEnumerable <PriceEpisode> priceEpisodes, long ukprn, short collectionYear, int collectionPeriod, DateTime ilrSubmissionDateTime, string ilrFileName, long jobId) { Aim = aim; Learner = learner; PriceEpisodes.AddRange(FilterPriceEpisodes(priceEpisodes, collectionYear)); Ukprn = ukprn; AcademicYear = collectionYear; CollectionPeriod = collectionPeriod; IlrSubmissionDateTime = ilrSubmissionDateTime; IlrFileName = ilrFileName; JobId = jobId; }
protected FM36Learner CreateFM36Learner(TestSession session, Learner testLearner, DateTime startDate) { var learner = new FM36Learner { LearnRefNumber = testLearner.LearnRefNumber, ULN = testLearner.Uln }; var priceEpisode = new ESFA.DC.ILR.FundingService.FM36.FundingOutput.Model.Output.PriceEpisode { PriceEpisodeIdentifier = "pe-1", PriceEpisodeValues = new PriceEpisodeValues { EpisodeStartDate = startDate, EpisodeEffectiveTNPStartDate = startDate, PriceEpisodeCompletionElement = 3000, PriceEpisodeCompleted = false, PriceEpisodeTotalTNPPrice = 15000, TNP1 = 9000, TNP2 = 6000, PriceEpisodeInstalmentValue = 1000, PriceEpisodePlannedInstalments = 12, PriceEpisodeActualInstalments = null, PriceEpisodeBalancePayment = 0, PriceEpisodeFundLineType = testLearner.Course.FundingLineType, PriceEpisodeBalanceValue = 0, PriceEpisodeCompletionPayment = 3000, PriceEpisodeContractType = testLearner.IsLevyLearner ? "Levy Contract" : "Non-Levy Contract", PriceEpisodeOnProgPayment = 1000, PriceEpisodePlannedEndDate = startDate.AddMonths(12), PriceEpisodeAimSeqNumber = 1, PriceEpisodeCumulativePMRs = int.MaxValue }, PriceEpisodePeriodisedValues = new List <PriceEpisodePeriodisedValues>() }; var learningValues = new PriceEpisodePeriodisedValues { AttributeName = "PriceEpisodeOnProgPayment", }; Enumerable.Range(1, 12).ToList().ForEach(i => SetPeriodValue(i, learningValues, 1000)); var completionEarnings = new PriceEpisodePeriodisedValues { AttributeName = "PriceEpisodeCompletionPayment", }; SetPeriodValue(12, completionEarnings, 3000); var balancingEarnings = new PriceEpisodePeriodisedValues { AttributeName = "PriceEpisodeBalancePayment", }; var sfaContributionValues = new PriceEpisodePeriodisedValues { AttributeName = "PriceEpisodeSFAContribPct" }; Enumerable.Range(1, 12).ToList().ForEach(i => SetPeriodValue(i, sfaContributionValues, .9M)); learner.PriceEpisodes = new List <PriceEpisode>(new[] { priceEpisode }); priceEpisode.PriceEpisodePeriodisedValues.Add(learningValues); priceEpisode.PriceEpisodePeriodisedValues.Add(completionEarnings); priceEpisode.PriceEpisodePeriodisedValues.Add(balancingEarnings); priceEpisode.PriceEpisodePeriodisedValues.Add(sfaContributionValues); learner.LearningDeliveries = new List <LearningDelivery>(new[] { new LearningDelivery { AimSeqNumber = 1, LearningDeliveryValues = new LearningDeliveryValues { LearnStartDate = startDate, LearnDelInitialFundLineType = testLearner.Course.FundingLineType, PwayCode = testLearner.Course.PathwayCode, FworkCode = testLearner.Course.FrameworkCode, ProgType = testLearner.Course.ProgrammeType, StdCode = testLearner.Course.StandardCode, LearnAimRef = testLearner.Course.LearnAimRef, } } }); return(learner); }
private List <EarningPeriod> GetEarningPeriods(List <Earning> aimEarningSpecs, Aim aimSpec, ApprenticeshipContractTypeEarningsEvent onProgEarning, TransactionType tt, FM36Learner fm36Learner) { return(aimEarningSpecs .Select(e => new EarningPeriod { Amount = PriceEpisodeContractTypeMatchesAim(aimSpec.PriceEpisodes, e.PriceEpisodeIdentifier, onProgEarning) ? e.Values[tt] : 0M, Period = e.DeliveryCalendarPeriod, PriceEpisodeIdentifier = FindPriceEpisodeIdentifier(e.Values[tt], e, fm36Learner, tt) }) .Where(p => p.Period <= collectionPeriod.Period) .OrderBy(p => p.Period) .ToList()); }
private List <FunctionalSkillEarningsEvent> CreateFunctionalSkillEarningEvents(List <TransactionType> functionalSkillEarnings, List <Earning> aimEarningSpecs, FM36Learner fm36Learner, Learner learner, LearningAim learningAim, Aim aimSpec) { var contractTypes = EnumHelper.GetContractTypes(currentIlr, currentPriceEpisodes); var events = new List <FunctionalSkillEarningsEvent>(); contractTypes?.ForEach(c => { switch (c) { case ContractType.Act1: events.Add(new Act1FunctionalSkillEarningsEvent { CollectionPeriod = collectionPeriod, Ukprn = provider.Ukprn, Earnings = functionalSkillEarnings.Select(tt => new FunctionalSkillEarning { Type = (FunctionalSkillType)(int)tt, Periods = aimEarningSpecs.Select(e => new EarningPeriod { Amount = e.Values[tt], Period = e.DeliveryCalendarPeriod, PriceEpisodeIdentifier = FindPriceEpisodeIdentifier(e.Values[tt], e, fm36Learner, tt) }).ToList().AsReadOnly() }).ToList().AsReadOnly(), JobId = provider.JobId, Learner = learner, LearningAim = learningAim }); break; case ContractType.Act2: events.Add(new Act2FunctionalSkillEarningsEvent { CollectionPeriod = collectionPeriod, Ukprn = provider.Ukprn, Earnings = functionalSkillEarnings.Select(tt => new FunctionalSkillEarning { Type = (FunctionalSkillType)(int)tt, Periods = aimEarningSpecs.Select(e => new EarningPeriod { Amount = e.Values[tt], Period = e.DeliveryCalendarPeriod, PriceEpisodeIdentifier = FindPriceEpisodeIdentifier(e.Values[tt], e, fm36Learner, tt) }).ToList().AsReadOnly() }).ToList().AsReadOnly(), JobId = provider.JobId, Learner = learner, LearningAim = learningAim }); break; default: throw new InvalidOperationException( "Cannot create the EarningEventMatcher invalid contract type "); } }); events.ForEach(x => x.LearningAim.FundingLineType = aimSpec.FundingLineType); return(events); }
public IEnumerable <AppsIndicativeEarningsReportModel> Build(IReportServiceContext reportServiceContext, IReportServiceDependentData reportServiceDependentData) { var message = reportServiceDependentData.Get <IMessage>(); var fm36Data = reportServiceDependentData.Get <FM36Global>(); var appsIndicativeEarningsModels = new List <AppsIndicativeEarningsReportModel>(); var referenceData = reportServiceDependentData.Get <ReferenceDataRoot>(); IDictionary <string, LARSLearningDelivery> larsLearningDeliveries = BuildLarsLearningDeliveryDictionary(referenceData); IDictionary <int, LARSStandard> larsStandards = BuildLarsStandardDictionary(referenceData); IDictionary <string, FM36Learner> fm36Learners = BuildFm36LearnerDeliveryDictionary(fm36Data); foreach (var learner in message?.Learners?.Where(l => l != null) ?? Enumerable.Empty <ILearner>()) { FM36Learner fm36Learner = fm36Learners.GetValueOrDefault(learner.LearnRefNumber); foreach (var learningDelivery in learner.LearningDeliveries ?? Enumerable.Empty <ILearningDelivery>()) { if (learningDelivery.FundModel != FundModelConstants.FM36) { continue; } LARSLearningDelivery larsDelivery = larsLearningDeliveries.GetValueOrDefault(learningDelivery.LearnAimRef); LearningDelivery fm36LearningDelivery = fm36Learner?.LearningDeliveries?.FirstOrDefault(x => x.AimSeqNumber == learningDelivery.AimSeqNumber); string larsStandard = null; if (learningDelivery.StdCodeNullable != null) { larsStandard = larsStandards.GetValueOrDefault(learningDelivery.StdCodeNullable.Value)?.NotionalEndLevel ?? "NA"; } if (fm36Learner?.PriceEpisodes.Any() ?? false) { List <PriceEpisode> episodesInRange = fm36Learner.PriceEpisodes .Where(p => p.PriceEpisodeValues.EpisodeStartDate >= ReportingConstants.BeginningOfYear && p.PriceEpisodeValues.EpisodeStartDate <= ReportingConstants.EndOfYear && learningDelivery.AimSeqNumber == p.PriceEpisodeValues.PriceEpisodeAimSeqNumber) .ToList(); if (episodesInRange.Any()) { DateTime earliestEpisodeDate = episodesInRange.Select(x => x.PriceEpisodeValues.EpisodeStartDate ?? DateTime.MaxValue).Min(); foreach (PriceEpisode episodeAttribute in episodesInRange) { appsIndicativeEarningsModels.Add(BuildLineModel(learner, learningDelivery, fm36LearningDelivery, episodeAttribute, larsDelivery, larsStandard, episodeAttribute.PriceEpisodeValues.EpisodeStartDate == earliestEpisodeDate, true)); } continue; } } appsIndicativeEarningsModels.Add(BuildLineModel(learner, learningDelivery, fm36LearningDelivery, null, larsDelivery, larsStandard, false, false)); } } return(appsIndicativeEarningsModels .OrderBy(x => x.LearnRefNumber) .ThenByDescending(x => x.AimSeqNumber) .ThenByDescending(x => x.PriceEpisodeStartDate)); }
private async Task GenerateRowsAsync(IMessage ilrFile, FM36Global fm36Data, List <string> validLearners, List <AppsIndicativeEarningsModel> appsIndicativeEarningsModels, CancellationToken cancellationToken) { ILearner[] learners = ilrFile.Learners.Where(x => validLearners.Contains(x.LearnRefNumber)).ToArray(); string[] learnAimRefs = learners.SelectMany(x => x.LearningDeliveries).Select(x => x.LearnAimRef).Distinct().ToArray(); Dictionary <string, LarsLearningDelivery> larsLearningDeliveries = await _larsProviderService.GetLearningDeliveriesAsync(learnAimRefs, cancellationToken); foreach (ILearner learner in learners) { FM36Learner fm36Learner = fm36Data?.Learners?.SingleOrDefault(x => string.Equals(x.LearnRefNumber, learner.LearnRefNumber, StringComparison.OrdinalIgnoreCase)); foreach (ILearningDelivery learningDelivery in learner.LearningDeliveries) { if (learningDelivery.FundModel != 36) { continue; } string larsStandard = null; if (learningDelivery.StdCodeNullable != null) { larsStandard = await _larsProviderService.GetStandardAsync( learningDelivery.StdCodeNullable.Value, cancellationToken); } LarsLearningDelivery larsDelivery = larsLearningDeliveries.SingleOrDefault(x => string.Equals(x.Key, learningDelivery.LearnAimRef, StringComparison.OrdinalIgnoreCase)).Value; LearningDelivery fm36LearningDelivery = fm36Learner?.LearningDeliveries ?.SingleOrDefault(x => x.AimSeqNumber == learningDelivery.AimSeqNumber); if (fm36Learner?.PriceEpisodes.Any() ?? false) { List <PriceEpisode> episodesInRange = fm36Learner.PriceEpisodes .Where(p => p.PriceEpisodeValues.EpisodeStartDate >= Constants.BeginningOfYear && p.PriceEpisodeValues.EpisodeStartDate <= Constants.EndOfYear && learningDelivery.AimSeqNumber == p.PriceEpisodeValues.PriceEpisodeAimSeqNumber).ToList(); if (episodesInRange.Any()) { DateTime earliestEpisodeDate = episodesInRange.Select(x => x.PriceEpisodeValues.EpisodeStartDate ?? DateTime.MaxValue).Min(); bool earliestEpisode = false; foreach (PriceEpisode episodeAttribute in episodesInRange) { if (episodeAttribute.PriceEpisodeValues.EpisodeStartDate == earliestEpisodeDate) { earliestEpisode = true; } appsIndicativeEarningsModels.Add( _modelBuilder.BuildModel( learner, learningDelivery, fm36LearningDelivery, episodeAttribute, larsDelivery, larsStandard, earliestEpisode, true)); earliestEpisode = false; } continue; } } appsIndicativeEarningsModels.Add( _modelBuilder.BuildModel( learner, learningDelivery, fm36LearningDelivery, null, larsDelivery, larsStandard, false, false)); } } appsIndicativeEarningsModels.Sort(AppsIndicativeEarningsModelComparer); }
public ValidationResult Validate(FM36Learner learner) { return(new ValidationResult(LearnerRules .Select(rule => rule.IsValid(learner)) .ToList())); }
public async Task <FM36Global> GetFM36Data(IReportServiceContext reportServiceContext, CancellationToken cancellationToken) { await _getDataLock.WaitAsync(cancellationToken); try { if (_loadedDataAlready) { return(_fundingOutputs); } cancellationToken.ThrowIfCancellationRequested(); _loadedDataAlready = true; int ukPrn = reportServiceContext.Ukprn; if (string.Equals(reportServiceContext.CollectionName, "ILR1819", StringComparison.OrdinalIgnoreCase)) { string fm36Filename = reportServiceContext.FundingFM36OutputKey; string fm36 = await _storage.GetAsync(fm36Filename, cancellationToken); if (string.IsNullOrEmpty(fm36)) { _fundingOutputs = null; return(_fundingOutputs); } // await _blob.SaveAsync($"{jobContextMessage.KeyValuePairs[JobContextMessageKey.UkPrn]}_{jobContextMessage.JobId.ToString()}_Fm36.json", fm36, cancellationToken); _fundingOutputs = _jsonSerializationService.Deserialize <FM36Global>(fm36); } else { FM36Global fm36Global = new FM36Global(); using (var ilrContext = _ilrRulebaseContextFactory()) { var fm36GlobalDb = await ilrContext.AEC_globals.FirstOrDefaultAsync(x => x.UKPRN == ukPrn, cancellationToken); //AEC_LearningDelivery[] res = await ilrContext.AEC_LearningDelivery_Period.Where(x => x.UKPRN == ukPrn).Select(x => x.AEC_LearningDelivery) // .Include(x => x.AEC_LearningDelivery_PeriodisedValues).ToArrayAsync(cancellationToken); AEC_LearningDelivery[] res = await ilrContext.AEC_LearningDeliveries.Where(x => x.UKPRN == ukPrn) .Include(x => x.AEC_LearningDelivery_PeriodisedValues).ToArrayAsync(cancellationToken); IGrouping <string, AEC_LearningDelivery>[] learners = res.GroupBy(x => x.LearnRefNumber).ToArray(); fm36Global.Learners = new List <FM36Learner>(); foreach (IGrouping <string, AEC_LearningDelivery> albLearningDeliveries in learners) { var learningDeliveryDto = new List <ILR.FundingService.FM36.FundingOutput.Model.Output.LearningDelivery>(); foreach (var ld in albLearningDeliveries) { var ldPeriodisedValues = ld.AEC_LearningDelivery_PeriodisedValues.Select(ldpv => new LearningDeliveryPeriodisedValues() { AttributeName = ldpv.AttributeName, Period1 = ldpv.Period_1, Period2 = ldpv.Period_2, Period3 = ldpv.Period_3, Period4 = ldpv.Period_4, Period5 = ldpv.Period_5, Period6 = ldpv.Period_6, Period7 = ldpv.Period_7, Period8 = ldpv.Period_8, Period9 = ldpv.Period_9, Period10 = ldpv.Period_10, Period11 = ldpv.Period_11, Period12 = ldpv.Period_12 }).ToList(); learningDeliveryDto.Add(new LearningDelivery() { AimSeqNumber = ld.AimSeqNumber, LearningDeliveryPeriodisedValues = ldPeriodisedValues, LearningDeliveryValues = new LearningDeliveryValues() { LearnDelInitialFundLineType = ld.LearnDelInitialFundLineType // todo : rest of the properties } }); } FM36Learner learner = new FM36Learner() { LearnRefNumber = albLearningDeliveries.Key, LearningDeliveries = learningDeliveryDto }; fm36Global.Learners.Add(learner); } if (fm36GlobalDb != null) { fm36Global.LARSVersion = fm36GlobalDb.LARSVersion; fm36Global.RulebaseVersion = fm36GlobalDb.RulebaseVersion; fm36Global.UKPRN = fm36GlobalDb.UKPRN; } } _fundingOutputs = fm36Global; } } finally { _getDataLock.Release(); } return(_fundingOutputs); }