public void Maps_Required_Fields_From_Identified_Learner()
        {
            var requiredPayment = new CalculatedRequiredLevyAmount();

            mapper.Map(identifiedLearningAim, requiredPayment);
            requiredPayment.ShouldBeMappedTo(identifiedLearningAim);
        }
        public async Task ShouldRemovePreviousSuccessfulProviderJobSubmission()
        {
            var keys = new List <string> {
                "1", "2"
            };
            var successfulUkprn       = 23456;
            var requiredPaymentEvent1 = new CalculatedRequiredLevyAmount
            {
                EventId   = Guid.NewGuid(),
                AmountDue = 100,
                SfaContributionPercentage = 11,
                OnProgrammeEarningType    = OnProgrammeEarningType.Completion,
                Learner          = new Learner(),
                CollectionPeriod = new CollectionPeriod {
                    AcademicYear = 1920, Period = 1
                },
                Ukprn                 = successfulUkprn,
                AccountId             = 1,
                JobId                 = 1,
                IlrSubmissionDateTime = DateTime.Now.AddMinutes(-1)
            };
            var requiredPaymentEvent2 = new CalculatedRequiredLevyAmount
            {
                EventId   = Guid.NewGuid(),
                AmountDue = 100,
                SfaContributionPercentage = 11,
                OnProgrammeEarningType    = OnProgrammeEarningType.Completion,
                Learner          = new Learner(),
                CollectionPeriod = new CollectionPeriod {
                    AcademicYear = 1920, Period = 1
                },
                Ukprn                 = successfulUkprn,
                AccountId             = 1,
                JobId                 = 2,
                IlrSubmissionDateTime = DateTime.Now
            };

            generateSortedPaymentKeysMock
            .Setup(x => x.GeyKeys())
            .ReturnsAsync(keys)
            .Verifiable();

            eventCacheMock.Setup(c => c.TryGet("1", CancellationToken.None))
            .ReturnsAsync(() => new ConditionalValue <CalculatedRequiredLevyAmount>(true, requiredPaymentEvent1))
            .Verifiable();
            eventCacheMock.Setup(c => c.TryGet("2", CancellationToken.None))
            .ReturnsAsync(() => new ConditionalValue <CalculatedRequiredLevyAmount>(true, requiredPaymentEvent2))
            .Verifiable();

            eventCacheMock.Setup(c => c.Clear("1", CancellationToken.None)).Returns(Task.CompletedTask).Verifiable();

            // act
            await service.RemovePreviousSubmissions(requiredPaymentEvent2.JobId,
                                                    requiredPaymentEvent2.CollectionPeriod.Period,
                                                    requiredPaymentEvent2.CollectionPeriod.AcademicYear,
                                                    requiredPaymentEvent2.IlrSubmissionDateTime,
                                                    requiredPaymentEvent2.Ukprn);

            // assert
        }
        public async Task TestStoresRefundPayments()
        {
            // arrange
            long expectedUln   = 100;
            long expectedUkprn = 100;

            var requiredPaymentEvent = new CalculatedRequiredLevyAmount
            {
                Ukprn    = expectedUkprn,
                EventId  = Guid.NewGuid(),
                Priority = 1,
                Learner  = new Learner
                {
                    Uln = expectedUln
                },
                AccountId = 1,
                AmountDue = -500
            };

            eventCacheMock.Setup(c => c.AddOrReplace(requiredPaymentEvent.EventId.ToString(), requiredPaymentEvent, CancellationToken.None)).Returns(Task.CompletedTask)
            .Verifiable();

            refundSortKeysCacheMock
            .Setup(c => c.TryGet(CacheKeys.RefundPaymentsKeyListKey, CancellationToken.None))
            .ReturnsAsync(() => new ConditionalValue <List <string> >(false, null)).Verifiable();

            refundSortKeysCacheMock
            .Setup(c => c.AddOrReplace(CacheKeys.RefundPaymentsKeyListKey, It.Is <List <string> >(list => list.Count == 1), CancellationToken.None))
            .Returns(Task.CompletedTask).Verifiable();

            // act
            await service.AddRequiredPayment(requiredPaymentEvent);

            // assert in teardown
        }
コード例 #4
0
        public void TestEarningPeriodMap()
        {
            var earningPeriod = new EarningPeriod
            {
                ApprenticeshipId             = 101,
                ApprenticeshipPriceEpisodeId = 102,
                Period    = 1,
                AccountId = 103,
                Priority  = 104,
                SfaContributionPercentage = 1m,
                PriceEpisodeIdentifier    = "123-01",
                Amount       = 1000000,
                AgreedOnDate = DateTime.Today
            };
            var requiredPayment = new CalculatedRequiredLevyAmount
            {
                SfaContributionPercentage = .9m,
                OnProgrammeEarningType    = OnProgrammeEarningType.Balancing
            };

            // act
            mapper.Map(earningPeriod, requiredPayment);

            var act1RequiredPayment = requiredPayment;

            Assert.AreEqual(earningPeriod.Period, act1RequiredPayment.DeliveryPeriod);
            Assert.AreEqual(earningPeriod.ApprenticeshipId, act1RequiredPayment.ApprenticeshipId);
            Assert.AreEqual(earningPeriod.ApprenticeshipPriceEpisodeId, act1RequiredPayment.ApprenticeshipPriceEpisodeId);
            Assert.AreEqual(earningPeriod.AgreedOnDate, act1RequiredPayment.AgreedOnDate);
            Assert.AreEqual(earningPeriod.Priority, act1RequiredPayment.Priority);
            Assert.AreEqual(earningPeriod.SfaContributionPercentage, act1RequiredPayment.SfaContributionPercentage);
            Assert.AreEqual(OnProgrammeEarningType.Balancing, act1RequiredPayment.OnProgrammeEarningType);
        }
        public async Task ShouldSetMonthEndPaymentsProcessedFlag()
        {
            // arrange
            var keys = new List <string> {
                "1"
            };
            var requiredPaymentEvent = new CalculatedRequiredLevyAmount
            {
                EventId   = Guid.NewGuid(),
                AmountDue = 100,
                SfaContributionPercentage = 11,
                OnProgrammeEarningType    = OnProgrammeEarningType.Completion,
                Learner = new Learner(),
            };

            var balance           = 100m;
            var transferAllowance = 50;
            var levyPayment       = new LevyPayment {
                AmountDue = 55, Type = FundingSourceType.Levy
            };
            var employerCoInvestedPayment = new EmployerCoInvestedPayment {
                AmountDue = 44, Type = FundingSourceType.CoInvestedEmployer
            };
            var sfaCoInvestedPayment = new SfaCoInvestedPayment {
                AmountDue = 33, Type = FundingSourceType.CoInvestedSfa
            };
            var allPayments = new FundingSourcePayment[] { levyPayment, employerCoInvestedPayment, sfaCoInvestedPayment };

            generateSortedPaymentKeysMock
            .Setup(x => x.GeyKeys())
            .ReturnsAsync(keys)
            .Verifiable();

            eventCacheMock.Setup(c => c.TryGet("1", CancellationToken.None))
            .ReturnsAsync(() => new ConditionalValue <CalculatedRequiredLevyAmount>(true, requiredPaymentEvent))
            .Verifiable();

            levyAccountRepositoryMock.Setup(r => r.GetLevyAccount(666, CancellationToken.None))
            .ReturnsAsync(() => new LevyAccountModel {
                Balance = balance, TransferAllowance = transferAllowance
            })
            .Verifiable();

            levyBalanceServiceMock.Setup(s => s.Initialise(balance, transferAllowance)).Verifiable();

            processorMock.Setup(p => p.Process(It.IsAny <RequiredPayment>())).Returns(() => allPayments).Verifiable();

            eventCacheMock.Setup(c => c.Clear(It.IsAny <string>(), It.IsAny <CancellationToken>())).Returns(Task.CompletedTask);

            refundSortKeysCacheMock.Setup(c => c.Clear(CacheKeys.RefundPaymentsKeyListKey, CancellationToken.None)).Returns(Task.CompletedTask).Verifiable();
            transferPaymentSortKeysCacheMock.Setup(c => c.Clear(CacheKeys.SenderTransferKeyListKey, CancellationToken.None)).Returns(Task.CompletedTask).Verifiable();
            requiredPaymentSortKeysCacheMock.Setup(c => c.Clear(CacheKeys.RequiredPaymentKeyListKey, CancellationToken.None)).Returns(Task.CompletedTask).Verifiable();


            // act
            await service.HandleMonthEnd(666, 1);

            // assert
            monthEndCacheMock.Verify(x => x.AddOrReplace(It.Is <string>(key => key.Equals(CacheKeys.MonthEndCacheKey)), It.Is <bool>(value => value), It.IsAny <CancellationToken>()));
        }
        public void Maps_Required_Fields_From_Historic_Payment()
        {
            var requiredPayment = new CalculatedRequiredLevyAmount();

            mapper.Map(historicPayment, requiredPayment);
            requiredPayment.ShouldBeMappedTo(historicPayment);
        }
        public static long CalculateFundingAccountId(this CalculatedRequiredLevyAmount levyTransaction, bool isReceiverTransferPayment)
        {
            if (isReceiverTransferPayment)
            {
                return(levyTransaction.AccountId.GetValueOrDefault());
            }

            return(levyTransaction.IsTransfer() ? levyTransaction.TransferSenderAccountId.GetValueOrDefault() : levyTransaction.AccountId.GetValueOrDefault());
        }
 public static bool IsTransfer(this CalculatedRequiredLevyAmount message)
 {
     if (!message.AccountId.HasValue)
     {
         throw new InvalidOperationException($"The account id of the levy message is invalid.");
     }
     return(message.TransferSenderAccountId.HasValue &&
            message.TransferSenderAccountId != 0 &&
            message.AccountId != message.TransferSenderAccountId);
 }
 public long GetDestinationAccountId(CalculatedRequiredLevyAmount message)
 {
     if (!message.AccountId.HasValue)
     {
         throw new InvalidOperationException($"The account id of the levy message is invalid.");
     }
     return(message.IsTransfer()
         ? message.TransferSenderAccountId.Value
         : message.AccountId.Value);
 }
        public void MapperDoesNotChangeEventId()
        {
            var payment         = new ApprenticeshipContractType1EarningEvent();
            var requiredPayment = new CalculatedRequiredLevyAmount();

            var expected = requiredPayment.EventId;

            mapper.Map(payment, requiredPayment);

            requiredPayment.EventId.Should().Be(expected);
        }
        private async Task AddRefundPaymentToCache(CalculatedRequiredLevyAmount paymentEvent)
        {
            var keysValue = await refundSortKeysCache.TryGet(CacheKeys.RefundPaymentsKeyListKey).ConfigureAwait(false);

            var refundKeysList = keysValue.HasValue ? keysValue.Value : new List <string>();

            refundKeysList.Add(paymentEvent.EventId.ToString());
            await requiredPaymentsCache.AddOrReplace(paymentEvent.EventId.ToString(), paymentEvent).ConfigureAwait(false);

            await refundSortKeysCache.AddOrReplace(CacheKeys.RefundPaymentsKeyListKey, refundKeysList).ConfigureAwait(false);
        }
コード例 #12
0
        public PeriodisedRequiredPaymentEvent Create(EarningType earningType, int transactionType)
        {
            PeriodisedRequiredPaymentEvent paymentEvent = null;

            switch (earningType)
            {
            case EarningType.CoInvested:
                if (IsValidPaymentType <OnProgrammeEarningType>(transactionType))
                {
                    paymentEvent = new CalculatedRequiredCoInvestedAmount
                    {
                        OnProgrammeEarningType = (OnProgrammeEarningType)transactionType,
                    };
                }

                break;

            case EarningType.Incentive:
                if (IsValidPaymentType <IncentivePaymentType>(transactionType))
                {
                    paymentEvent = new CalculatedRequiredIncentiveAmount
                    {
                        Type = (IncentivePaymentType)transactionType,
                    };
                }

                break;

            case EarningType.Levy:
                if (IsValidPaymentType <OnProgrammeEarningType>(transactionType))
                {
                    paymentEvent = new CalculatedRequiredLevyAmount
                    {
                        OnProgrammeEarningType = (OnProgrammeEarningType)transactionType,
                    };
                }

                break;

            default:
                throw new InvalidOperationException(
                          $"Unknown earning type found: {earningType:G}. Cannot create the PeriodisedRequiredPaymentEvent.");
            }

            if (paymentEvent == null)
            {
                logger.LogError(
                    $"Invalid EarningType and TransactionType combination: EarningType: {earningType:G}, TransactionType: {transactionType}");
            }

            return(paymentEvent);
        }
        public void Process_BuildsFundingSourceEvents_Correctly()
        {
            var amount = new CalculatedRequiredLevyAmount
            {
                AccountId   = eventEmployerAccountId,
                AmountDue   = amountDue,
                AgreementId = "Agreement Two",
                SfaContributionPercentage = sfaContributionPercentage,
                TransferSenderAccountId   = transferSenderEmployerAccountId
            };

            fundingSourcePayments = new List <FundingSourcePayment>
            {
                new EmployerCoInvestedPayment {
                    AmountDue = 540, Type = FundingSourceType.CoInvestedSfa
                },
                new LevyPayment {
                    AmountDue = 700, Type = FundingSourceType.Levy
                },
                new TransferPayment {
                    AmountDue = 900, Type = FundingSourceType.Transfer
                }
            };

            processor.Setup(x => x.Process(It.IsAny <RequiredPayment>()))
            .Returns(fundingSourcePayments);

            mapper.Setup(x => x.Map <FundingSourcePaymentEvent>(It.IsAny <EmployerCoInvestedPayment>())).Returns(new EmployerCoInvestedFundingSourcePaymentEvent());
            mapper.Setup(x => x.Map <FundingSourcePaymentEvent>(It.IsAny <LevyPayment>())).Returns(new LevyFundingSourcePaymentEvent());
            mapper.Setup(x => x.Map <FundingSourcePaymentEvent>(It.IsAny <TransferPayment>())).Returns(new TransferFundingSourcePaymentEvent());

            var results = service.BuildFundingSourcePaymentsForRequiredPayment(amount, transferSenderEmployerAccountId, jobId);

            processor.Verify(x => x.Process(It.Is <RequiredPayment>(rp =>
                                                                    rp.SfaContributionPercentage == sfaContributionPercentage &&
                                                                    rp.AmountDue == amountDue &&
                                                                    rp.IsTransfer
                                                                    )), Times.Once);

            mapper.VerifyAll();
            mapper.Verify(x => x.Map(It.IsAny <CalculatedRequiredLevyAmount>(), It.IsAny <FundingSourcePaymentEvent>()), Times.Exactly(3));

            results.Count.Should().Be(3);

            results.Should().Contain(x => x.GetType() == typeof(LevyFundingSourcePaymentEvent));
            results.Should().Contain(x => x.GetType() == typeof(EmployerCoInvestedFundingSourcePaymentEvent));
            results.Should().Contain(x => x.GetType() == typeof(TransferFundingSourcePaymentEvent));

            results.ForEach(x => x.JobId.Should().Be(jobId));
        }
 private static void AssertCalculatedRequiredLevyAmountEvent(CalculatedRequiredLevyAmount listOfCalculatedRequiredLevyAmounts, PaymentModel historicalPayment, IdentifiedRemovedLearningAim message)
 {
     listOfCalculatedRequiredLevyAmounts.AgreementId.Should().Be(historicalPayment.AgreementId);
     listOfCalculatedRequiredLevyAmounts.AgreedOnDate.Should().Be(null);
     listOfCalculatedRequiredLevyAmounts.AccountId.Should().Be(historicalPayment.AccountId);
     listOfCalculatedRequiredLevyAmounts.ActualEndDate.Should().Be(historicalPayment.ActualEndDate);
     listOfCalculatedRequiredLevyAmounts.AmountDue.Should().Be(-100);
     listOfCalculatedRequiredLevyAmounts.ApprenticeshipEmployerType.Should().Be(historicalPayment.ApprenticeshipEmployerType);
     listOfCalculatedRequiredLevyAmounts.ApprenticeshipId.Should().Be(historicalPayment.ApprenticeshipId);
     listOfCalculatedRequiredLevyAmounts.ApprenticeshipPriceEpisodeId.Should().Be(historicalPayment.ApprenticeshipPriceEpisodeId);
     listOfCalculatedRequiredLevyAmounts.CollectionPeriod.Period.Should().Be(message.CollectionPeriod.Period);
     listOfCalculatedRequiredLevyAmounts.CollectionPeriod.AcademicYear.Should().Be(message.CollectionPeriod.AcademicYear);
     listOfCalculatedRequiredLevyAmounts.CompletionAmount.Should().Be(historicalPayment.CompletionAmount);
     listOfCalculatedRequiredLevyAmounts.CompletionStatus.Should().Be(historicalPayment.CompletionStatus);
     listOfCalculatedRequiredLevyAmounts.ContractType.Should().Be(historicalPayment.ContractType);
     listOfCalculatedRequiredLevyAmounts.DeliveryPeriod.Should().Be(historicalPayment.DeliveryPeriod);
     listOfCalculatedRequiredLevyAmounts.EarningEventId.Should().Be(Guid.Empty);
     listOfCalculatedRequiredLevyAmounts.EventTime.Should().BeCloseTo(DateTimeOffset.UtcNow, 100);
     listOfCalculatedRequiredLevyAmounts.IlrFileName.Should().Be(null);
     listOfCalculatedRequiredLevyAmounts.IlrSubmissionDateTime.Should().Be(message.IlrSubmissionDateTime);
     listOfCalculatedRequiredLevyAmounts.InstalmentAmount.Should().Be(historicalPayment.InstalmentAmount);
     listOfCalculatedRequiredLevyAmounts.JobId.Should().Be(message.JobId);
     listOfCalculatedRequiredLevyAmounts.Learner.ReferenceNumber.Should().Be(historicalPayment.LearnerReferenceNumber);
     listOfCalculatedRequiredLevyAmounts.Learner.Uln.Should().Be(historicalPayment.LearnerUln);
     listOfCalculatedRequiredLevyAmounts.LearningAim.FrameworkCode.Should().Be(historicalPayment.LearningAimFrameworkCode);
     listOfCalculatedRequiredLevyAmounts.LearningAim.FundingLineType.Should().Be(historicalPayment.LearningAimFundingLineType);
     listOfCalculatedRequiredLevyAmounts.LearningAim.PathwayCode.Should().Be(historicalPayment.LearningAimPathwayCode);
     listOfCalculatedRequiredLevyAmounts.LearningAim.ProgrammeType.Should().Be(historicalPayment.LearningAimProgrammeType);
     listOfCalculatedRequiredLevyAmounts.LearningAim.Reference.Should().Be(historicalPayment.LearningAimReference);
     listOfCalculatedRequiredLevyAmounts.LearningAim.SequenceNumber.Should().Be(0);
     listOfCalculatedRequiredLevyAmounts.LearningAim.StandardCode.Should().Be(historicalPayment.LearningAimStandardCode);
     listOfCalculatedRequiredLevyAmounts.LearningAim.StartDate.Should().Be(historicalPayment.StartDate);
     listOfCalculatedRequiredLevyAmounts.LearningStartDate.Should().Be(historicalPayment.LearningStartDate);
     listOfCalculatedRequiredLevyAmounts.NumberOfInstalments.Should().Be(historicalPayment.NumberOfInstalments);
     listOfCalculatedRequiredLevyAmounts.OnProgrammeEarningType.Should().Be((OnProgrammeEarningType)historicalPayment.TransactionType);
     listOfCalculatedRequiredLevyAmounts.PlannedEndDate.Should().Be(historicalPayment.PlannedEndDate);
     listOfCalculatedRequiredLevyAmounts.PriceEpisodeIdentifier.Should().Be(historicalPayment.PriceEpisodeIdentifier);
     listOfCalculatedRequiredLevyAmounts.Priority.Should().Be(0);
     listOfCalculatedRequiredLevyAmounts.ReportingAimFundingLineType.Should().Be(historicalPayment.ReportingAimFundingLineType);
     listOfCalculatedRequiredLevyAmounts.SfaContributionPercentage.Should().Be(historicalPayment.SfaContributionPercentage);
     listOfCalculatedRequiredLevyAmounts.StartDate.Should().Be(historicalPayment.StartDate);
     listOfCalculatedRequiredLevyAmounts.TransactionType.Should().Be(historicalPayment.TransactionType);
     listOfCalculatedRequiredLevyAmounts.TransferSenderAccountId.Should().Be(historicalPayment.TransferSenderAccountId);
     listOfCalculatedRequiredLevyAmounts.Ukprn.Should().Be(historicalPayment.Ukprn);
 }
        public async Task AddRequiredPayment(CalculatedRequiredLevyAmount paymentEvent)
        {
            if (paymentEvent.AmountDue < 0)
            {
                await AddRefundPaymentToCache(paymentEvent);

                return;
            }

            if (paymentEvent.IsTransfer())
            {
                await AddTransferPaymentToCache(paymentEvent);

                return;
            }

            await AddRequiredPaymentToCache(paymentEvent);
        }
        private async Task AddRequiredPaymentToCache(CalculatedRequiredLevyAmount paymentEvent)
        {
            var keysValue = await requiredPaymentSortKeysCache.TryGet(CacheKeys.RequiredPaymentKeyListKey).ConfigureAwait(false);

            var requiredPaymentKeysList = keysValue.HasValue ? keysValue.Value : new List <RequiredPaymentSortKeyModel>();

            var newRequiredPaymentSortKey = new RequiredPaymentSortKeyModel
            {
                Id           = paymentEvent.EventId.ToString(),
                Uln          = paymentEvent.Learner.Uln,
                Ukprn        = paymentEvent.Ukprn,
                AgreedOnDate = paymentEvent.AgreedOnDate ?? DateTime.MinValue
            };

            requiredPaymentKeysList.Add(newRequiredPaymentSortKey);

            await requiredPaymentsCache.AddOrReplace(newRequiredPaymentSortKey.Id, paymentEvent).ConfigureAwait(false);

            await requiredPaymentSortKeysCache.AddOrReplace(CacheKeys.RequiredPaymentKeyListKey, requiredPaymentKeysList).ConfigureAwait(false);
        }
コード例 #17
0
        public async Task HandleRequiredPayment(CalculatedRequiredLevyAmount message)
        {
            try
            {
                using (var operation = telemetry.StartOperation("LevyFundedService.HandleRequiredPayment", message.EventId.ToString()))
                {
                    var stopwatch = Stopwatch.StartNew();
                    paymentLogger.LogVerbose($"Handling RequiredPayment for {Id}, Job: {message.JobId}, UKPRN: {message.Ukprn}, Account: {message.AccountId}");
                    await fundingSourceService.AddRequiredPayment(message).ConfigureAwait(false);

                    paymentLogger.LogInfo($"Finished handling required payment for {Id}, Job: {message.JobId}, UKPRN: {message.Ukprn}, Account: {message.AccountId}");
                    telemetry.TrackDuration("LevyFundedService.HandleRequiredPayment", stopwatch, message);
                    telemetry.StopOperation(operation);
                }
            }
            catch (Exception e)
            {
                paymentLogger.LogError($"Error handling required levy payment. Error:{e.Message}", e);
                throw;
            }
        }
        public async Task TestStoresTransferPayment()
        {
            // arrange
            long expectedUln = 100;

            var requiredPaymentEvent = new CalculatedRequiredLevyAmount
            {
                Ukprn    = 100,
                EventId  = Guid.NewGuid(),
                Priority = 1,
                Learner  = new Learner
                {
                    Uln = expectedUln
                },
                AccountId = 1,
                TransferSenderAccountId = 9
            };

            eventCacheMock.Setup(c => c.AddOrReplace(requiredPaymentEvent.EventId.ToString(), requiredPaymentEvent, CancellationToken.None))
            .Returns(Task.CompletedTask)
            .Verifiable();

            transferPaymentSortKeysCacheMock
            .Setup(c => c.TryGet(CacheKeys.SenderTransferKeyListKey, CancellationToken.None))
            .ReturnsAsync(() => new ConditionalValue <List <TransferPaymentSortKeyModel> >(false, null)).Verifiable();

            transferPaymentSortKeysCacheMock
            .Setup(c =>
                   c.AddOrReplace(CacheKeys.SenderTransferKeyListKey,
                                  It.Is <List <TransferPaymentSortKeyModel> >(list => list.Count == 1 && list[0].Uln == expectedUln), CancellationToken.None))
            .Returns(Task.CompletedTask).Verifiable();

            // act
            await service.AddRequiredPayment(requiredPaymentEvent);

            // assert in teardown
        }
コード例 #19
0
        public void Setup()
        {
            requiredPaymentEvent = new CalculatedRequiredLevyAmount
            {
                AmountDue        = 1000.00m,
                CollectionPeriod = CollectionPeriodFactory.CreateFromAcademicYearAndPeriod(1819, 1),
                DeliveryPeriod   = 1,
                EventTime        = DateTime.UtcNow,
                JobId            = 1,
                Learner          = new Learner
                {
                    ReferenceNumber = "001",
                    Uln             = 1234567890
                },
                OnProgrammeEarningType = OnProgrammeEarningType.Learning,
                LearningAim            = new LearningAim
                {
                    FrameworkCode = 403
                },
                PriceEpisodeIdentifier    = "1819-P01",
                SfaContributionPercentage = 0.9m,
                Ukprn = 10000,

                AgreementId                = "11",
                Priority                   = 13,
                EventId                    = Guid.NewGuid(),
                AccountId                  = 1000000,
                IlrSubmissionDateTime      = DateTime.Today,
                EarningEventId             = Guid.NewGuid(),
                ContractType               = ContractType.Act1,
                ApprenticeshipEmployerType = ApprenticeshipEmployerType.Levy,
                ApprenticeshipId           = 12,
            };
            mapperConfiguration = AutoMapperConfigurationFactory.CreateMappingConfig();
            autoMapper          = mapperConfiguration.CreateMapper();
        }
コード例 #20
0
        public void TestPayableEarningEventMap()
        {
            // arrange
            var payableEarning = CreatePayableEarning();
            PeriodisedRequiredPaymentEvent requiredPayment = new CalculatedRequiredLevyAmount
            {
                SfaContributionPercentage = .9m,
                OnProgrammeEarningType    = OnProgrammeEarningType.Completion
            };

            // act
            mapper.Map(payableEarning, requiredPayment);

            // assert
            AssertCommonProperties(requiredPayment, payableEarning);

            var act1RequiredPayment = (CalculatedRequiredLevyAmount)requiredPayment;

            Assert.AreEqual(payableEarning.AgreementId, act1RequiredPayment.AgreementId);
            Assert.AreEqual(.9m, act1RequiredPayment.SfaContributionPercentage);
            Assert.AreEqual(OnProgrammeEarningType.Completion, act1RequiredPayment.OnProgrammeEarningType);
            Assert.AreEqual(payableEarning.EarningEventId, act1RequiredPayment.EarningEventId);
            Assert.AreNotEqual(payableEarning.EventId, act1RequiredPayment.EarningEventId);
        }
コード例 #21
0
        public void SetUp()
        {
            ukprn     = 3383742;
            accountId = 78934234;
            message   = new ProcessUnableToFundTransferFundingSourcePayment
            {
                AccountId = accountId,
                Ukprn     = ukprn
            };

            calculatedRequiredLevyAmount = new CalculatedRequiredLevyAmount
            {
                Ukprn = ukprn
            };

            levyAccountModel = new LevyAccountModel
            {
                AccountId         = accountId,
                Balance           = 3000,
                TransferAllowance = 2000
            };

            mappedLevyAccountModel = new LevyAccountModel
            {
                AccountId         = accountId,
                Balance           = 3000,
                TransferAllowance = 2000
            };

            fundingSourcePaymentEvents = new List <FundingSourcePaymentEvent>
            {
                new LevyFundingSourcePaymentEvent
                {
                    AccountId = accountId,
                    Ukprn     = ukprn,
                    AmountDue = 1000
                }
            };

            paymentLogger      = new Mock <IPaymentLogger>();
            mapper             = new Mock <IMapper>();
            monthEndCache      = new Mock <IDataCache <bool> >();
            levyAccountCache   = new Mock <IDataCache <LevyAccountModel> >();
            levyBalanceService = new Mock <ILevyBalanceService>();
            fundingSourcePaymentEventBuilder   = new Mock <IFundingSourcePaymentEventBuilder>();
            levyTransactionBatchStorageService = new Mock <ILevyTransactionBatchStorageService>();

            mapper.Setup(x => x.Map <CalculatedRequiredLevyAmount>(message))
            .Returns(calculatedRequiredLevyAmount);

            mapper.Setup(x => x.Map <LevyAccountModel>(levyAccountModel))
            .Returns(mappedLevyAccountModel);

            levyAccountCache.Setup(x => x.TryGet(CacheKeys.LevyBalanceKey, It.IsAny <CancellationToken>()))
            .ReturnsAsync(new ConditionalValue <LevyAccountModel>(true, levyAccountModel));

            fundingSourcePaymentEventBuilder.Setup(x => x.BuildFundingSourcePaymentsForRequiredPayment(
                                                       It.IsAny <CalculatedRequiredLevyAmount>(),
                                                       accountId,
                                                       It.IsAny <long>()))
            .Returns(fundingSourcePaymentEvents);

            service = new TransferFundingSourceEventGenerationService(
                paymentLogger.Object,
                mapper.Object,
                monthEndCache.Object,
                levyAccountCache.Object,
                levyBalanceService.Object,
                fundingSourcePaymentEventBuilder.Object,
                levyTransactionBatchStorageService.Object
                );
        }
        public async Task ProcessesUnableToFundTransferPayments()
        {
            // arrange
            var keys = new List <string> {
                "1"
            };
            var requiredPaymentEvent = new CalculatedRequiredLevyAmount
            {
                EventId   = Guid.NewGuid(),
                AmountDue = 100,
                SfaContributionPercentage = 11,
                OnProgrammeEarningType    = OnProgrammeEarningType.Completion,
                Learner   = new Learner(),
                AccountId = 666,
                TransferSenderAccountId = 2
            };

            var balance           = 100m;
            var transferAllowance = 50;
            var transferPayment   = new TransferPayment {
                AmountDue = 55, Type = FundingSourceType.Transfer
            };
            var unableToFundTransferPayment = new UnableToFundTransferPayment {
                AmountDue = 44, Type = FundingSourceType.Transfer
            };
            var allPayments = new FundingSourcePayment[] { transferPayment, unableToFundTransferPayment };

            generateSortedPaymentKeysMock
            .Setup(x => x.GeyKeys())
            .ReturnsAsync(keys)
            .Verifiable();

            eventCacheMock.Setup(c => c.TryGet("1", CancellationToken.None))
            .ReturnsAsync(() => new ConditionalValue <CalculatedRequiredLevyAmount>(true, requiredPaymentEvent))
            .Verifiable();

            levyAccountRepositoryMock.Setup(r => r.GetLevyAccount(666, CancellationToken.None))
            .ReturnsAsync(() => new LevyAccountModel {
                Balance = balance, TransferAllowance = transferAllowance
            })
            .Verifiable();

            levyBalanceServiceMock.Setup(s => s.Initialise(balance, transferAllowance)).Verifiable();

            processorMock.Setup(p => p.Process(It.IsAny <RequiredPayment>())).Returns(() => allPayments).Verifiable();

            eventCacheMock.Setup(c => c.Clear("1", CancellationToken.None)).Returns(Task.CompletedTask).Verifiable();

            refundSortKeysCacheMock.Setup(c => c.Clear(CacheKeys.RefundPaymentsKeyListKey, CancellationToken.None)).Returns(Task.CompletedTask).Verifiable();
            transferPaymentSortKeysCacheMock.Setup(c => c.Clear(CacheKeys.SenderTransferKeyListKey, CancellationToken.None)).Returns(Task.CompletedTask).Verifiable();
            requiredPaymentSortKeysCacheMock.Setup(c => c.Clear(CacheKeys.RequiredPaymentKeyListKey, CancellationToken.None)).Returns(Task.CompletedTask).Verifiable();

            // act
            var fundingSourcePayments = await service.HandleMonthEnd(666, 1);

            // assert
            fundingSourcePayments.Should().HaveCount(2);
            fundingSourcePayments[0].Should().BeOfType <TransferFundingSourcePaymentEvent>();
            fundingSourcePayments[1].Should().BeOfType <ProcessUnableToFundTransferFundingSourcePayment>();

            fundingSourcePayments[0].AmountDue.Should().Be(55);
            fundingSourcePayments[1].AmountDue.Should().Be(44);
        }
        public async Task TestMonthEndPaymentProcessing()
        {
            // arrange
            var keys = new List <string> {
                "1", "99", "4", "9"
            };
            var expectedKeys         = new Queue <string>(new[] { "1", "99", "4", "9" });
            var expectedKeys2        = new Queue <string>(new[] { "1", "99", "4", "9" });
            var requiredPaymentEvent = new CalculatedRequiredLevyAmount
            {
                EventId   = Guid.NewGuid(),
                AmountDue = 100,
                SfaContributionPercentage = 11,
                OnProgrammeEarningType    = OnProgrammeEarningType.Completion,
                Priority = 4,
                Learner  = new Learner()
            };

            var value                = new ConditionalValue <CalculatedRequiredLevyAmount>(true, requiredPaymentEvent);
            var requiredPayments     = new Queue <ConditionalValue <CalculatedRequiredLevyAmount> >(new[] { value, value, value, value });
            var fundingSourcePayment = new LevyPayment {
                AmountDue = 55, Type = FundingSourceType.CoInvestedEmployer
            };

            var balance           = 100m;
            var transferAllowance = 50;

            generateSortedPaymentKeysMock
            .Setup(x => x.GeyKeys())
            .ReturnsAsync(keys)
            .Verifiable();

            eventCacheMock.Setup(c => c.TryGet(It.IsAny <string>(), CancellationToken.None))
            .ReturnsAsync(requiredPayments.Dequeue())
            .Callback <string, CancellationToken>((k, c) => Assert.AreEqual(expectedKeys.Dequeue(), k))
            .Verifiable();

            levyAccountRepositoryMock.Setup(r => r.GetLevyAccount(666, CancellationToken.None))
            .ReturnsAsync(() => new LevyAccountModel {
                AccountId = 666, Balance = balance, TransferAllowance = transferAllowance
            })
            .Verifiable();

            levyBalanceServiceMock.Setup(s => s.Initialise(balance, transferAllowance)).Verifiable();

            processorMock.Setup(p => p.Process(It.IsAny <RequiredPayment>()))
            .Returns(() => new[] { fundingSourcePayment })
            .Verifiable();

            eventCacheMock.Setup(c => c.Clear(It.IsAny <string>(), CancellationToken.None))
            .Returns(Task.CompletedTask)
            .Callback <string, CancellationToken>((k, c) => Assert.AreEqual(expectedKeys2.Dequeue(), k))
            .Verifiable();

            refundSortKeysCacheMock.Setup(c => c.Clear(CacheKeys.RefundPaymentsKeyListKey, CancellationToken.None)).Returns(Task.CompletedTask).Verifiable();
            transferPaymentSortKeysCacheMock.Setup(c => c.Clear(CacheKeys.SenderTransferKeyListKey, CancellationToken.None)).Returns(Task.CompletedTask).Verifiable();
            requiredPaymentSortKeysCacheMock.Setup(c => c.Clear(CacheKeys.RequiredPaymentKeyListKey, CancellationToken.None)).Returns(Task.CompletedTask).Verifiable();

            levyAccountCacheMock.Setup(c => c.AddOrReplace(CacheKeys.LevyBalanceKey, It.Is <LevyAccountModel>(model => model.AccountId == 666), It.IsAny <CancellationToken>()))
            .Returns(Task.CompletedTask)
            .Verifiable();

            // act
            await service.HandleMonthEnd(666, 1);

            // assert
            Assert.AreEqual(0, expectedKeys.Count);
            Assert.AreEqual(0, expectedKeys2.Count);
        }
        public async Task TestRegisterSubsequentRequiredPayment()
        {
            // arrange
            var  eventId       = Guid.NewGuid();
            long expectedUln   = 100;
            long expectedUkprn = 100;

            var keys = new List <RequiredPaymentSortKeyModel>
            {
                new RequiredPaymentSortKeyModel
                {
                    Ukprn        = expectedUkprn,
                    Uln          = 1,
                    Id           = Guid.NewGuid().ToString(),
                    AgreedOnDate = DateTime.Today
                },
                new RequiredPaymentSortKeyModel
                {
                    Ukprn        = expectedUkprn,
                    Uln          = 2,
                    Id           = Guid.NewGuid().ToString(),
                    AgreedOnDate = DateTime.Today
                }
            };

            var requiredPaymentEvent = new CalculatedRequiredLevyAmount
            {
                Ukprn     = expectedUkprn,
                StartDate = DateTime.Today,
                EventId   = eventId,
                Priority  = 4,
                Learner   = new Learner
                {
                    Uln = expectedUln
                },
                AccountId = 1,
            };

            eventCacheMock.Setup(c => c.AddOrReplace(requiredPaymentEvent.EventId.ToString(), requiredPaymentEvent, CancellationToken.None))
            .Returns(Task.CompletedTask)
            .Verifiable();

            requiredPaymentSortKeysCacheMock
            .Setup(c => c.TryGet(CacheKeys.RequiredPaymentKeyListKey, CancellationToken.None))
            .ReturnsAsync(() => new ConditionalValue <List <RequiredPaymentSortKeyModel> >(true, keys))
            .Verifiable();

            requiredPaymentSortKeysCacheMock
            .Setup(c =>
                   c.AddOrReplace(CacheKeys.RequiredPaymentKeyListKey,
                                  It.Is <List <RequiredPaymentSortKeyModel> >(list => list.Count == 3 &&
                                                                              list[2].Uln == expectedUln &&
                                                                              list[2].Ukprn == expectedUkprn), CancellationToken.None))
            .Returns(Task.CompletedTask)
            .Verifiable();

            // act
            await service.AddRequiredPayment(requiredPaymentEvent);

            // assert
        }
コード例 #25
0
        public List <FundingSourcePaymentEvent> BuildFundingSourcePaymentsForRequiredPayment(CalculatedRequiredLevyAmount requiredPaymentEvent,
                                                                                             long employerAccountId, long jobId)
        {
            var fundingSourceEvents = new List <FundingSourcePaymentEvent>();
            var requiredPayment     = new RequiredPayment
            {
                SfaContributionPercentage = requiredPaymentEvent.SfaContributionPercentage,
                AmountDue  = requiredPaymentEvent.AmountDue,
                IsTransfer = employerAccountId != requiredPaymentEvent.AccountId &&
                             requiredPaymentEvent.TransferSenderAccountId.HasValue &&
                             requiredPaymentEvent.TransferSenderAccountId == employerAccountId
            };

            var fundingSourcePayments = processor.Process(requiredPayment);

            foreach (var fundingSourcePayment in fundingSourcePayments)
            {
                var fundingSourceEvent = mapper.Map <FundingSourcePaymentEvent>(fundingSourcePayment);
                mapper.Map(requiredPaymentEvent, fundingSourceEvent);
                fundingSourceEvent.JobId = jobId;
                fundingSourceEvents.Add(fundingSourceEvent);
            }

            return(fundingSourceEvents);
        }
        public void Setup()
        {
            var requiredPaymentEventEventId = Guid.NewGuid();
            var earningEventId = Guid.NewGuid();
            var utcNow         = DateTime.UtcNow;

            unableToFundTransferFundingSourcePayment = new ProcessUnableToFundTransferFundingSourcePayment
            {
                EventId                = requiredPaymentEventEventId,
                EarningEventId         = earningEventId,
                EventTime              = utcNow,
                RequiredPaymentEventId = requiredPaymentEventEventId,

                AmountDue        = 1000.00m,
                CollectionPeriod = CollectionPeriodFactory.CreateFromAcademicYearAndPeriod(1819, 1),
                DeliveryPeriod   = 1,
                JobId            = 1,
                Learner          = new Learner
                {
                    ReferenceNumber = "001",
                    Uln             = 1234567890
                },
                LearningAim = new LearningAim
                {
                    FrameworkCode = 403
                },
                PriceEpisodeIdentifier    = "1819-P01",
                SfaContributionPercentage = 0.9m,
                Ukprn = 10000,

                AccountId             = 1000000,
                IlrSubmissionDateTime = DateTime.Today,

                ContractType = ContractType.Act1,
                ApprenticeshipEmployerType = ApprenticeshipEmployerType.Levy,
                ApprenticeshipId           = 12,
                CompletionAmount           = 10,
                CompletionStatus           = 1,
                InstalmentAmount           = 10,
                StartDate                    = utcNow,
                TransactionType              = TransactionType.Balancing,
                ActualEndDate                = utcNow,
                FundingSourceType            = FundingSourceType.Levy,
                IlrFileName                  = "Test",
                LearningStartDate            = utcNow,
                NumberOfInstalments          = 1,
                PlannedEndDate               = utcNow,
                ApprenticeshipPriceEpisodeId = 1,
                TransferSenderAccountId      = 10,
                ReportingAimFundingLineType  = "Test"
            };

            expectedEvent = new CalculatedRequiredLevyAmount
            {
                EventId        = requiredPaymentEventEventId,
                EarningEventId = earningEventId,
                EventTime      = utcNow,

                AmountDue        = 1000.00m,
                CollectionPeriod = CollectionPeriodFactory.CreateFromAcademicYearAndPeriod(1819, 1),
                DeliveryPeriod   = 1,
                JobId            = 1,
                Learner          = new Learner
                {
                    ReferenceNumber = "001",
                    Uln             = 1234567890
                },
                LearningAim = new LearningAim
                {
                    FrameworkCode = 403
                },
                PriceEpisodeIdentifier    = "1819-P01",
                SfaContributionPercentage = 0.9m,
                Ukprn = 10000,

                AccountId             = 1000000,
                IlrSubmissionDateTime = DateTime.Today,

                ContractType = ContractType.Act1,
                ApprenticeshipEmployerType = ApprenticeshipEmployerType.Levy,
                ApprenticeshipId           = 12,
                CompletionAmount           = 10,
                CompletionStatus           = 1,
                InstalmentAmount           = 10,
                StartDate                    = utcNow,
                ActualEndDate                = utcNow,
                IlrFileName                  = "Test",
                LearningStartDate            = utcNow,
                NumberOfInstalments          = 1,
                PlannedEndDate               = utcNow,
                ApprenticeshipPriceEpisodeId = 1,
                OnProgrammeEarningType       = OnProgrammeEarningType.Balancing,
                TransferSenderAccountId      = 10,
                ReportingAimFundingLineType  = "Test"
            };

            mapperConfiguration = AutoMapperConfigurationFactory.CreateMappingConfig();
            autoMapper          = mapperConfiguration.CreateMapper();
        }
 private async Task AddRequiredPayment(CalculatedRequiredLevyAmount calculatedRequiredLevyAmount)
 {
     await levyTransactionBatchStorageService.StoreLevyTransactions(new List <CalculatedRequiredLevyAmount> {
         calculatedRequiredLevyAmount
     }, CancellationToken.None, true);
 }
 public static bool IsRefund(this CalculatedRequiredLevyAmount calculatedRequiredLevyAmount)
 {
     return(calculatedRequiredLevyAmount.AmountDue < 0);
 }