Beispiel #1
0
        /// <summary>
        /// If all apprenticeships share the same Funding Cap, this is it.
        /// If they have different funding caps, or there is no trainingprogram or apprenticeships,
        /// or there is not enough data to calculate the funding cap for each apprenticeship, this is null
        /// </summary>
        private int?CalculateCommonFundingCap()
        {
            if (TrainingProgramme == null || !Apprenticeships.Any())
            {
                return(null);
            }

            if (!IsLinkedToChangeOfPartyRequest && Apprenticeships.Any(a => !a.StartDate.HasValue))
            {
                return(null);
            }

            int firstFundingCap = IsLinkedToChangeOfPartyRequest
                          ? TrainingProgramme.FundingCapOn(Apprenticeships.First().OriginalStartDate.Value)
                          : TrainingProgramme.FundingCapOn(Apprenticeships.First().StartDate.Value);

            // check for magic 0, which means unable to calculate a funding cap (e.g. date out of bounds)
            if (firstFundingCap == 0)
            {
                return(null);
            }

            if (Apprenticeships.Skip(1).Any(a => TrainingProgramme.FundingCapOn(a.StartDate.Value) != firstFundingCap))
            {
                return(null);
            }

            return(firstFundingCap);
        }
Beispiel #2
0
        /// <summary>
        /// If all apprenticeships share the same Funding Cap, this is it.
        /// If they have different funding caps, or there is no trainingprogram or apprenticeships,
        /// or there is not enough data to calculate the funding cap for each apprenticeship, this is null
        /// </summary>
        private int?CalculateCommonFundingCap()
        {
            if (TrainingProgramme == null || !Apprenticeships.Any())
            {
                return(null);
            }

            if (Apprenticeships.Any(a => !a.StartDate.HasValue))
            {
                return(null);
            }

            var firstFundingCap = TrainingProgramme.FundingCapOn(Apprenticeships.First().StartDate.Value);

            // check for magic 0, which means unable to calculate a funding cap (e.g. date out of bounds)
            if (firstFundingCap == 0)
            {
                return(null);
            }

            if (Apprenticeships.Skip(1).Any(a => TrainingProgramme.FundingCapOn(a.StartDate.Value) != firstFundingCap))
            {
                return(null);
            }

            return(firstFundingCap);
        }
Beispiel #3
0
        public async Task GivenTheApprenticeshipsStatusChangesAsFollows(Table table)
        {
            var statuses      = table.CreateSet <ApprenticeshipStatusPeriod>();
            var validStatuses = statuses.Select(status => new
            {
                status.Status,
                CollectionPeriod = new CollectionPeriodBuilder().WithSpecDate(status.CollectionPeriod).Build(),
                status.Identifier,
                status.StoppedDate
            })
                                .Where(status => status.CollectionPeriod.AcademicYear == CurrentCollectionPeriod.AcademicYear &&
                                       status.CollectionPeriod.Period == CurrentCollectionPeriod.Period)
                                .ToList();

            foreach (var validStatus in validStatuses)
            {
                var apprenticeship = Apprenticeships.FirstOrDefault(appr => appr.Identifier == validStatus.Identifier);
                if (apprenticeship == null)
                {
                    throw new InvalidOperationException($"Apprenticeship not found. Identifier: {validStatus.Identifier}");
                }
                Console.WriteLine($"Updating status of apprenticeship. Identifier: {validStatus.Identifier}, apprenticeship id: {apprenticeship.ApprenticeshipId}, status: {validStatus.Status}");
                await UpdateApprenticeshipStatus(apprenticeship.ApprenticeshipId, validStatus.Status, validStatus.StoppedDate);
            }
        }
        /// <summary>
        /// Creates a cohort with a draft apprenticeship
        /// </summary>
        internal Cohort(long providerId,
                        long accountId,
                        long accountLegalEntityId,
                        long?transferSenderId,
                        DraftApprenticeshipDetails draftApprenticeshipDetails,
                        Party originatingParty,
                        UserInfo userInfo) : this(providerId, accountId, accountLegalEntityId, transferSenderId, originatingParty, userInfo)
        {
            CheckDraftApprenticeshipDetails(draftApprenticeshipDetails);
            ValidateDraftApprenticeshipDetails(draftApprenticeshipDetails, false);
            WithParty  = originatingParty;
            EditStatus = originatingParty.ToEditStatus();
            IsDraft    = true;

            var draftApprenticeship = new DraftApprenticeship(draftApprenticeshipDetails, originatingParty);

            Apprenticeships.Add(draftApprenticeship);

            Publish(() => new DraftApprenticeshipCreatedEvent(draftApprenticeship.Id, Id, draftApprenticeship.Uln, draftApprenticeship.ReservationId, draftApprenticeship.CreatedOn.Value));

            StartTrackingSession(UserAction.CreateCohort, originatingParty, accountId, providerId, userInfo);
            ChangeTrackingSession.TrackInsert(this);
            ChangeTrackingSession.TrackInsert(draftApprenticeship);
            ChangeTrackingSession.CompleteTrackingSession();
        }
Beispiel #5
0
        /// <remarks>
        /// if the training program is not effective on the start date, the user will get a validation message when creating the apprenticeship
        /// (e.g. This training course is only available to apprentices with a start date after 04 2018)
        /// so we shouldn't see FundingCapOn returning 0 (when the start date is outside of a funding cap)
        /// but if we see it, we treat the apprenticeship as *not* over the funding limit
        /// </remarks>
        private int CalculateApprenticeshipsOverFundingLimit()
        {
            if (TrainingProgramme == null)
            {
                return(0);
            }

            return(Apprenticeships.Count(x => x.IsOverFundingLimit(TrainingProgramme, IsLinkedToChangeOfPartyRequest)));
        }
Beispiel #6
0
        /// <remarks>
        /// if the training program is not effective on the start date, the user will get a validation message when creating the apprenticeship
        /// (e.g. This training course is only available to apprentices with a start date after 04 2018)
        /// so we shouldn't see FundingCapOn returning 0 (when the start date is outside of a funding cap)
        /// but if we see it, we treat the apprenticeship as *not* over the funding limit
        /// </remarks>
        private int CalculateApprenticeshipsOverFundingLimit()
        {
            if (TrainingProgramme == null)
            {
                return(0);
            }

            return(Apprenticeships.Count(x => x.IsOverFundingLimit(TrainingProgramme)));
        }
        private IEnumerable <DomainError> BuildUlnValidationFailures(DraftApprenticeshipDetails draftApprenticeshipDetails)
        {
            if (string.IsNullOrWhiteSpace(draftApprenticeshipDetails.Uln))
            {
                yield break;
            }

            if (Apprenticeships.Any(a => a.Id != draftApprenticeshipDetails.Id && a.Uln == draftApprenticeshipDetails.Uln))
            {
                yield return(new DomainError(nameof(draftApprenticeshipDetails.Uln), "The unique learner number has already been used for an apprentice in this cohort"));
            }
        }
Beispiel #8
0
 public void Clear()
 {
     Apprenticeships.Clear();
     Courses.Clear();
     Frameworks.Clear();
     ProgTypes.Clear();
     Providers.Clear();
     SectorSubjectAreaTier1s.Clear();
     SectorSubjectAreaTier2s.Clear();
     Standards.Clear();
     StandardSectorCodes.Clear();
     Venues.Clear();
 }
        /// <summary>
        /// Creates a Cohort from a Change of Party Request
        /// </summary>
        internal Cohort(long providerId,
                        long accountId,
                        long accountLegalEntityId,
                        Apprenticeship apprenticeship,
                        Guid?reservationId,
                        ChangeOfPartyRequest changeOfPartyRequest,
                        UserInfo userInfo)
            : this(providerId,
                   accountId,
                   accountLegalEntityId,
                   null,
                   changeOfPartyRequest.OriginatingParty,
                   userInfo)
        {
            ChangeOfPartyRequestId = changeOfPartyRequest.Id;

            Approvals = changeOfPartyRequest.IsPreApproved();

            WithParty = changeOfPartyRequest.OriginatingParty.GetOtherParty();
            IsDraft   = false;

            if (changeOfPartyRequest.ChangeOfPartyType == ChangeOfPartyRequestType.ChangeProvider)
            {
                TransferSenderId = apprenticeship.Cohort.TransferSenderId;
            }

            var draftApprenticeship = apprenticeship.CreateCopyForChangeOfParty(changeOfPartyRequest, reservationId);

            Apprenticeships.Add(draftApprenticeship);

            //Retained for backwards-compatibility:
            EditStatus       = WithParty.ToEditStatus();
            LastAction       = LastAction.Amend;
            CommitmentStatus = CommitmentStatus.Active;

            Publish(() => new CohortWithChangeOfPartyCreatedEvent(Id, changeOfPartyRequest.Id, changeOfPartyRequest.OriginatingParty, DateTime.UtcNow, userInfo));

            if (changeOfPartyRequest.ChangeOfPartyType == ChangeOfPartyRequestType.ChangeEmployer)
            {
                Publish(() => new CohortAssignedToEmployerEvent(Id, DateTime.UtcNow, Party.Provider));
            }
            else
            {
                Publish(() => new CohortAssignedToProviderEvent(Id, DateTime.UtcNow));
            }

            StartTrackingSession(UserAction.CreateCohortWithChangeOfParty, changeOfPartyRequest.OriginatingParty, accountId, providerId, userInfo);
            ChangeTrackingSession.TrackInsert(this);
            ChangeTrackingSession.TrackInsert(draftApprenticeship);
            ChangeTrackingSession.CompleteTrackingSession();
        }
 private void RemoveDraftApprenticeship(DraftApprenticeship draftApprenticeship)
 {
     ChangeTrackingSession.TrackDelete(draftApprenticeship);
     LastUpdatedOn = DateTime.UtcNow;
     Apprenticeships.Remove(draftApprenticeship);
     Publish(() => new DraftApprenticeshipDeletedEvent
     {
         DraftApprenticeshipId = draftApprenticeship.Id,
         CohortId      = draftApprenticeship.CommitmentId,
         Uln           = draftApprenticeship.Uln,
         ReservationId = draftApprenticeship.ReservationId,
         DeletedOn     = DateTime.UtcNow
     });
 }
        public ProcessFullyApprovedCohortCommandFixture SetApprovedApprenticeships(bool isFundedByTransfer)
        {
            var provider = new Provider {
                Name = "Test Provider"
            };
            var account            = new Account(1, "", "", "", DateTime.UtcNow);
            var accountLegalEntity = new AccountLegalEntity(account, 1, 1, "", "", "Test Employer", OrganisationType.Charities, "", DateTime.UtcNow);

            AutoFixture.Inject(account);

            var cohortBuilder = AutoFixture.Build <Cohort>()
                                .Without(c => c.Apprenticeships)
                                .With(c => c.AccountLegalEntity, accountLegalEntity)
                                .With(c => c.Provider, provider)
                                .With(x => x.IsDeleted, false);

            if (!isFundedByTransfer)
            {
                cohortBuilder.Without(c => c.TransferSenderId).Without(c => c.TransferApprovalActionedOn);
            }

            var apprenticeshipBuilder = AutoFixture.Build <Apprenticeship>().Without(a => a.DataLockStatus).Without(a => a.EpaOrg).Without(a => a.ApprenticeshipUpdate).Without(a => a.Continuation).Without(a => a.PreviousApprenticeship);
            var cohort1 = cohortBuilder.With(c => c.Id, Command.CohortId).Create();
            var cohort2 = cohortBuilder.Create();

            var apprenticeship1 = apprenticeshipBuilder.With(a => a.Cohort, cohort1).Create();
            var apprenticeship2 = apprenticeshipBuilder.With(a => a.Cohort, cohort1).Create();
            var apprenticeship3 = apprenticeshipBuilder.With(a => a.Cohort, cohort2).Create();

            var apprenticeships1 = new[] { apprenticeship1, apprenticeship2 };
            var apprenticeships2 = new[] { apprenticeship1, apprenticeship2, apprenticeship3 };

            Apprenticeships.AddRange(apprenticeships1);
            Db.Object.AccountLegalEntities.Add(accountLegalEntity);
            Db.Object.Providers.Add(provider);
            Db.Object.Apprenticeships.AddRange(apprenticeships2);

            Db.Object.SaveChanges();

            return(this);
        }
Beispiel #12
0
        private async Task ValidateDataLockError(Table table, Provider provider)
        {
            var dataLockErrors = table.CreateSet <DataLockError>().ToList();

            foreach (var dataLockError in dataLockErrors)
            {
                if (string.IsNullOrWhiteSpace(dataLockError.Apprenticeship))
                {
                    continue;
                }

                var apprenticeship = Apprenticeships.FirstOrDefault(a => a.Identifier == dataLockError.Apprenticeship) ??
                                     throw new Exception($"Can't find a matching apprenticeship for Identifier {dataLockError.Apprenticeship}");

                dataLockError.ApprenticeshipId = apprenticeship.ApprenticeshipId;
            }

            var matcher = new EarningFailedDataLockMatcher(provider, TestSession, CurrentCollectionPeriod, dataLockErrors);

            await WaitForIt(() => matcher.MatchPayments(), "DataLock Failed event check failure");
        }
        public virtual bool IsApprovedByAllParties => WithParty == Party.None; //todo: use new Approvals flag

        public DraftApprenticeship AddDraftApprenticeship(DraftApprenticeshipDetails draftApprenticeshipDetails, Party creator, UserInfo userInfo)
        {
            CheckIsWithParty(creator);
            ValidateDraftApprenticeshipDetails(draftApprenticeshipDetails, false);

            StartTrackingSession(UserAction.AddDraftApprenticeship, creator, EmployerAccountId, ProviderId, userInfo);
            ChangeTrackingSession.TrackUpdate(this);

            var draftApprenticeship = new DraftApprenticeship(draftApprenticeshipDetails, creator);

            Apprenticeships.Add(draftApprenticeship);
            Approvals = Party.None;
            UpdatedBy(creator, userInfo);
            LastUpdatedOn = DateTime.UtcNow;

            ChangeTrackingSession.TrackInsert(draftApprenticeship);
            ChangeTrackingSession.CompleteTrackingSession();

            Publish(() => new DraftApprenticeshipCreatedEvent(draftApprenticeship.Id, Id, draftApprenticeship.Uln, draftApprenticeship.ReservationId, draftApprenticeship.CreatedOn.Value));
            return(draftApprenticeship);
        }
Beispiel #14
0
        public void Update(ApprenticeshipViewModel model)
        {
            var entity = new Apprenticeships();

            entity.ApprenticeshipID = model.ApprenticeshipID;
            entity.PostDate         = model.PostDate;
            entity.DurationMonths   = model.DurationMonths;
            entity.Name             = model.Name;
            entity.Title            = model.Title;
            entity.Description      = model.Description;
            entity.Country          = model.Country;
            entity.Commitment       = model.Commitment;
            entity.Compensation     = model.Compensation;
            entity.JobSector        = model.JobSector;
            entity.Status           = model.Status;
            entity.StartDate        = model.StartDate;
            entity.EndDate          = model.EndDate;
            entity.EmployerID       = model.EmployerID;

            entities.Apprenticeships.Attach(entity);
            entities.Entry(entity).State = EntityState.Modified;
            entities.SaveChanges();
        }
Beispiel #15
0
        public void Create(ApprenticeshipViewModel model)
        {
            Apprenticeships entity = new Apprenticeships()
            {
                ApprenticeshipID = model.ApprenticeshipID,
                PostDate         = model.PostDate,
                DurationMonths   = model.DurationMonths,
                Name             = model.Name,
                Title            = model.Title,
                Description      = model.Description,
                Country          = model.Country,
                Commitment       = model.Commitment,
                Compensation     = model.Compensation,
                JobSector        = model.JobSector,
                Status           = model.Status,
                StartDate        = model.StartDate,
                EndDate          = model.EndDate,
                EmployerID       = model.EmployerID
            };

            entities.Apprenticeships.Add(entity);
            entities.SaveChanges();
        }
Beispiel #16
0
 public void AddApprenticeship(Apprenticeship apprenticeship)
 {
     Apprenticeships.Add(apprenticeship);
 }