private async Task <Certificate> CreateNewCertificate(StartCertificateRequest request)
        {
            _logger.LogInformation("CreateNewCertificate Before Get Ilr from db");
            var ilr = await _ilrRepository.Get(request.Uln, request.StandardCode);

            _logger.LogInformation("CreateNewCertificate Before Get Organisation from db");
            var organisation = await _organisationQueryRepository.GetByUkPrn(request.UkPrn);

            _logger.LogInformation("CreateNewCertificate Before Get Standard from API");
            var standard = await _standardService.GetStandard(ilr.StdCode);

            _logger.LogInformation("CreateNewCertificate Before Get Provider from API");
            var provider = await GetProviderFromUkprn(ilr.UkPrn);

            var certData = new CertificateData()
            {
                LearnerGivenNames       = ilr.GivenNames,
                LearnerFamilyName       = ilr.FamilyName,
                LearningStartDate       = ilr.LearnStartDate,
                StandardReference       = standard.ReferenceNumber,
                StandardName            = standard.Title,
                StandardLevel           = standard.StandardData.Level.GetValueOrDefault(),
                StandardPublicationDate = standard.StandardData.EffectiveFrom.GetValueOrDefault(),
                FullName     = $"{ilr.GivenNames} {ilr.FamilyName}",
                ProviderName = provider.ProviderName,
                EpaDetails   = new EpaDetails {
                    Epas = new List <EpaRecord>()
                }
            };

            _logger.LogInformation("CreateNewCertificate Before create new Certificate");
            var newCertificate = await _certificateRepository.New(
                new Certificate()
            {
                Uln                  = request.Uln,
                StandardCode         = request.StandardCode,
                ProviderUkPrn        = ilr.UkPrn,
                OrganisationId       = organisation.Id,
                CreatedBy            = request.Username,
                CertificateData      = JsonConvert.SerializeObject(certData),
                Status               = CertificateStatus.Draft,
                CertificateReference = "",
                LearnRefNumber       = ilr.LearnRefNumber,
                CreateDay            = DateTime.UtcNow.Date
            });

            newCertificate.CertificateReference = newCertificate.CertificateReferenceId.ToString().PadLeft(8, '0');

            // need to update EPA Reference too
            certData.EpaDetails.EpaReference = newCertificate.CertificateReference;
            newCertificate.CertificateData   = JsonConvert.SerializeObject(certData);

            _logger.LogInformation("CreateNewCertificate Before Update Cert in db");
            await _certificateRepository.Update(newCertificate, request.Username, null);

            _logger.LogInformation(LoggingConstants.CertificateStarted);
            _logger.LogInformation($"Certificate with ID: {newCertificate.Id} Started with reference of {newCertificate.CertificateReference}");

            return(newCertificate);
        }
Beispiel #2
0
        private async Task <Certificate> CreateNewCertificate(CreateBatchCertificateRequest request)
        {
            _logger.LogInformation("CreateNewCertificate Before Get Ilr from db");
            var ilr = await _ilrRepository.Get(request.Uln, request.StandardCode);

            if (ilr is null)
            {
                _logger.LogWarning($"CreateNewCertificate Did not find ILR for Uln {request.Uln} and StandardCode {request.StandardCode}");
                return(null);
            }

            _logger.LogInformation("CreateNewCertificate Before Get Organisation from db");
            var organisation = await _organisationQueryRepository.GetByUkPrn(request.UkPrn);

            _logger.LogInformation("CreateNewCertificate Before Get Standard from API");
            var standard = await _standardService.GetStandard(ilr.StdCode);

            _logger.LogInformation("CreateNewCertificate Before Get Provider from API");
            var provider = await GetProviderFromUkprn(ilr.UkPrn);

            var certData = CombineCertificateData(request.CertificateData, ilr, standard, provider);

            var certificate = await _certificateRepository.GetCertificate(request.Uln, request.StandardCode);

            if (certificate == null)
            {
                _logger.LogInformation("CreateNewCertificate Before create new Certificate");
                certificate = await _certificateRepository.New(
                    new Certificate()
                {
                    Uln                  = request.Uln,
                    StandardCode         = request.StandardCode,
                    ProviderUkPrn        = ilr.UkPrn,
                    OrganisationId       = organisation.Id,
                    CreatedBy            = ExternalApiConstants.ApiUserName,
                    CertificateData      = JsonConvert.SerializeObject(certData),
                    Status               = CertificateStatus.Draft, // NOTE: Web & Staff always creates Draft first
                    CertificateReference = string.Empty,
                    LearnRefNumber       = ilr.LearnRefNumber,
                    CreateDay            = DateTime.UtcNow.Date
                });
            }
            else
            {
                _logger.LogInformation("CreateNewCertificate Before resurrecting deleted Certificate");
                certData.EpaDetails.EpaReference = certificate.CertificateReference;
                certificate.CertificateData      = JsonConvert.SerializeObject(certData);
                certificate.Status = CertificateStatus.Draft;
                await _certificateRepository.Update(certificate, ExternalApiConstants.ApiUserName, CertificateActions.Start);
            }

            _logger.LogInformation(LoggingConstants.CertificateStarted);
            _logger.LogInformation($"Certificate with ID: {certificate.Id} Started with reference of {certificate.CertificateReference}");

            return(await CertificateHelpers.ApplyStatusInformation(_certificateRepository, _contactQueryRepository, certificate));
        }
        private async Task<Organisation> UpdateOrganisationIfExists(CreateOrganisationRequest createOrganisationRequest)
        {
            if (!createOrganisationRequest.EndPointAssessorUkprn.HasValue)
            {
                return null;
            }

            var existingOrganisation =
                await _organisationQueryRepository.GetByUkPrn(createOrganisationRequest.EndPointAssessorUkprn.Value);

            if (existingOrganisation != null
                && existingOrganisation.EndPointAssessorOrganisationId == createOrganisationRequest.EndPointAssessorOrganisationId
                && existingOrganisation.Status == OrganisationStatus.Deleted)
            {
                return await _organisationRepository.UpdateOrganisation(new Organisation
                {
                    EndPointAssessorName = createOrganisationRequest.EndPointAssessorName,
                    EndPointAssessorOrganisationId = existingOrganisation.EndPointAssessorOrganisationId,
                    PrimaryContact = existingOrganisation.PrimaryContact,
                    Status = OrganisationStatus.New
                     
                });
            }

            return null;
        }
        public CreateBatchCertificateRequestValidator(
            IStringLocalizer <BatchCertificateRequestValidator> localiser,
            IOrganisationQueryRepository organisationQueryRepository,
            IIlrRepository ilrRepository,
            ICertificateRepository certificateRepository,
            IStandardService standardService)
        {
            Include(new BatchCertificateRequestValidator(localiser, organisationQueryRepository, ilrRepository, standardService));

            RuleFor(m => m.CertificateReference).Empty().WithMessage("Certificate reference must be empty").DependentRules(() =>
            {
                RuleFor(m => m).CustomAsync(async(m, context, cancellation) =>
                {
                    var existingCertificate = await certificateRepository.GetCertificate(m.Uln, m.StandardCode);
                    var sumbittingEpao      = await organisationQueryRepository.GetByUkPrn(m.UkPrn);
                    var learnerDetails      = await ilrRepository.Get(m.Uln, m.StandardId.GetValueOrDefault());

                    if (existingCertificate != null && existingCertificate.Status != CertificateStatus.Deleted)
                    {
                        if (sumbittingEpao?.Id != existingCertificate.OrganisationId)
                        {
                            context.AddFailure(new ValidationFailure("CertificateData", $"Your organisation is not the creator of the EPA"));
                        }
                        else if (existingCertificate.Status == CertificateStatus.Draft)
                        {
                            var certData = JsonConvert.DeserializeObject <CertificateData>(existingCertificate.CertificateData);

                            if (!string.IsNullOrEmpty(certData.OverallGrade) && certData.AchievementDate.HasValue && !string.IsNullOrEmpty(certData.ContactPostCode))
                            {
                                context.AddFailure(new ValidationFailure("CertificateData", $"Certificate already exists: {existingCertificate.CertificateReference}"));
                            }
                            else if (!EpaOutcome.Pass.Equals(certData.EpaDetails?.LatestEpaOutcome, StringComparison.InvariantCultureIgnoreCase))
                            {
                                context.AddFailure(new ValidationFailure("CertificateData", $"Latest EPA Outcome has not passed"));
                            }
                        }
                        else
                        {
                            context.AddFailure(new ValidationFailure("CertificateData", $"Certificate already exists: {existingCertificate.CertificateReference}"));
                        }
                    }

                    if (learnerDetails != null)
                    {
                        if (learnerDetails.CompletionStatus == (int)CompletionStatus.Withdrawn)
                        {
                            context.AddFailure(new ValidationFailure("LearnerDetails", "Cannot find the apprentice details"));
                        }
                        else if (learnerDetails.CompletionStatus == (int)CompletionStatus.TemporarilyWithdrawn)
                        {
                            context.AddFailure(new ValidationFailure("LearnerDetails", "Cannot find the apprentice details"));
                        }
                    }
                    else
                    {
                        context.AddFailure(new ValidationFailure("LearnerDetails", $"Learner details for ULN: {m.Uln} not found"));
                    }
                });
            });
        }
        private async Task <LearnerDetailForExternalApi> GetLearnerDetails(GetBatchLearnerRequest request, StandardCollation standard)
        {
            LearnerDetailForExternalApi learnerDetail = null;

            if (standard != null)
            {
                var learner = await _ilrRepository.Get(request.Uln, standard.StandardId.GetValueOrDefault());

                if (learner != null)
                {
                    var epao = await _organisationRepository.GetByUkPrn(learner.UkPrn);

                    learnerDetail = new LearnerDetailForExternalApi()
                    {
                        Uln                            = learner.Uln,
                        GivenNames                     = learner.GivenNames,
                        FamilyName                     = learner.FamilyName,
                        LearnerStartDate               = learner.LearnStartDate,
                        LearnerReferenceNumber         = learner.LearnRefNumber,
                        PlannedEndDate                 = learner.PlannedEndDate,
                        CompletionStatus               = learner.CompletionStatus,
                        Standard                       = standard,
                        EndPointAssessorOrganisationId = epao?.EndPointAssessorOrganisationId ?? learner.EpaOrgId,
                        UkPrn                          = epao?.EndPointAssessorUkprn ?? learner.UkPrn,
                        OrganisationName               = epao?.EndPointAssessorName ?? "Unknown"
                    };
                }
                else
                {
                    _logger.LogError($"Could not find learner for ULN {request.Uln} and StandardCode {standard.StandardId.GetValueOrDefault()}");
                }
            }

            return(learnerDetail);
        }
Beispiel #6
0
        public BatchEpaRequestValidator(IStringLocalizer <BatchEpaRequestValidator> localiser, IOrganisationQueryRepository organisationQueryRepository, IIlrRepository ilrRepository, IStandardService standardService)
        {
            RuleFor(m => m.UkPrn).InclusiveBetween(10000000, 99999999).WithMessage("The UKPRN should contain exactly 8 numbers");

            RuleFor(m => m.FamilyName).NotEmpty().WithMessage("Provide apprentice family name");
            RuleFor(m => m.StandardCode).GreaterThan(0).WithMessage("Provide a valid Standard").DependentRules(() =>
            {
                RuleFor(m => m).CustomAsync(async(m, context, cancellation) =>
                {
                    if (!string.IsNullOrEmpty(m.StandardReference))
                    {
                        var collatedStandard = await standardService.GetStandard(m.StandardReference);
                        if (m.StandardCode != collatedStandard?.StandardId)
                        {
                            context.AddFailure("StandardReference and StandardCode must be for the same Standard");
                        }
                    }
                });
            });

            RuleFor(m => m.Uln).InclusiveBetween(1000000000, 9999999999).WithMessage("ULN should contain exactly 10 numbers").DependentRules(() =>
            {
                When(m => m.StandardCode > 0 && !string.IsNullOrEmpty(m.FamilyName), () =>
                {
                    RuleFor(m => m).CustomAsync(async(m, context, canellation) =>
                    {
                        var requestedIlr   = await ilrRepository.Get(m.Uln, m.StandardCode);
                        var sumbittingEpao = await organisationQueryRepository.GetByUkPrn(m.UkPrn);

                        if (requestedIlr is null || !string.Equals(requestedIlr.FamilyName, m.FamilyName, StringComparison.InvariantCultureIgnoreCase))
                        {
                            context.AddFailure(new ValidationFailure("Uln", "ULN, FamilyName and Standard not found."));
                        }
                        else if (sumbittingEpao is null)
                        {
                            context.AddFailure(new ValidationFailure("UkPrn", "Specified UKPRN not found"));
                        }
                        else if (requestedIlr.CompletionStatus == (int)CompletionStatus.Withdrawn)
                        {
                            context.AddFailure(new ValidationFailure("LearnerDetails", "Cannot find the apprentice details"));
                        }
                        else if (requestedIlr.CompletionStatus == (int)CompletionStatus.TemporarilyWithdrawn)
                        {
                            context.AddFailure(new ValidationFailure("LearnerDetails", "Cannot find the apprentice details"));
                        }
                        else
                        {
                            var providedStandards = await standardService.GetEpaoRegisteredStandards(sumbittingEpao.EndPointAssessorOrganisationId);

                            if (!providedStandards.Any(s => s.StandardCode == m.StandardCode))
                            {
                                context.AddFailure(new ValidationFailure("StandardCode", "Your organisation is not approved to assess this Standard"));
                            }
                        }
                    });
                });
        public GetBatchCertificateRequestValidator(IStringLocalizer <GetBatchCertificateRequestValidator> localiser, IOrganisationQueryRepository organisationQueryRepository, ILearnerRepository learnerRepository, ICertificateRepository certificateRepository, IStandardService standardService)
        {
            RuleFor(m => m.UkPrn).InclusiveBetween(10000000, 99999999).WithMessage("The UKPRN should contain exactly 8 numbers");

            RuleFor(m => m.FamilyName).NotEmpty().WithMessage("Provide apprentice family name");
            RuleFor(m => m.StandardCode).GreaterThan(0).WithMessage("Provide a valid Standard");

            RuleFor(m => m.Uln).InclusiveBetween(1000000000, 9999999999).WithMessage("ULN should contain exactly 10 numbers").DependentRules(() =>
            {
                When(m => m.StandardCode > 0 && !string.IsNullOrEmpty(m.FamilyName), () =>
                {
                    RuleFor(m => m).CustomAsync(async(m, context, cancellation) =>
                    {
                        // NOTE: Currently we're making the Certificate & Learner/ILR record both mandatory - this is wrong fixing it!
                        var submittingEpao = await organisationQueryRepository.GetByUkPrn(m.UkPrn);

                        if (submittingEpao is null)
                        {
                            context.AddFailure(new ValidationFailure("UkPrn", "Specified UKPRN not found"));
                        }
                        else
                        {
                            var existingCertificateCreatedByCallingEpao = await certificateRepository.GetCertificateByUlnOrgIdLastnameAndStandardCode(m.Uln, submittingEpao.EndPointAssessorOrganisationId, m.FamilyName, m.StandardCode);

                            if (existingCertificateCreatedByCallingEpao == null)
                            {
                                var requestedLearner    = await learnerRepository.Get(m.Uln, m.StandardCode);
                                var existingCertificate = await certificateRepository.GetCertificate(m.Uln, m.StandardCode);
                                var providedStandards   = await standardService.GetEpaoRegisteredStandards(submittingEpao.EndPointAssessorOrganisationId);

                                if (!providedStandards.Any(s => s.StandardCode == m.StandardCode))
                                {
                                    context.AddFailure(new ValidationFailure("StandardCode", "Your organisation is not approved to assess this Standard"));
                                }

                                if (existingCertificate != null)
                                {
                                    var certData = JsonConvert.DeserializeObject <CertificateData>(existingCertificate.CertificateData ?? "{}");

                                    if (!certData.LearnerFamilyName.Equals(m.FamilyName, StringComparison.InvariantCultureIgnoreCase))
                                    {
                                        context.AddFailure(new ValidationFailure("FamilyName", $"Cannot find apprentice with the specified Uln, FamilyName & Standard"));
                                    }
                                    else if (!EpaOutcome.Pass.Equals(certData.EpaDetails?.LatestEpaOutcome, StringComparison.InvariantCultureIgnoreCase))
                                    {
                                        context.AddFailure(new ValidationFailure("Uln", $"Cannot find certificate with the specified Uln, FamilyName & Standard"));
                                    }
                                }
                                else if (requestedLearner is null || !string.Equals(requestedLearner.FamilyName, m.FamilyName, StringComparison.InvariantCultureIgnoreCase))
                                {
                                    context.AddFailure(new ValidationFailure("Uln", "Cannot find apprentice with the specified Uln, FamilyName & Standard"));
                                }
                            }
                        }
                    });
Beispiel #8
0
        public async Task <Certificate> Handle(StartCertificatePrivateRequest request, CancellationToken cancellationToken)
        {
            var organisation = await _organisationQueryRepository.GetByUkPrn(request.UkPrn);

            var certificate = await _certificateRepository.GetPrivateCertificate(request.Uln,
                                                                                 organisation.EndPointAssessorOrganisationId);

            if (certificate != null)
            {
                if (certificate.Status == Domain.Consts.CertificateStatus.Deleted)
                {
                    var certData = JsonConvert.DeserializeObject <CertificateData>(certificate.CertificateData);
                    certData.LearnerFamilyName    = request.LastName;
                    certificate.CertificateData   = JsonConvert.SerializeObject(certData);
                    certificate.IsPrivatelyFunded = true;
                    await _certificateRepository.Update(certificate, request.Username, string.Empty, false);
                }
                return(certificate);
            }

            return(await CreateNewCertificate(request));
        }
        private async Task <Certificate> GetCertificate(GetBatchCertificateRequest request)
        {
            _logger.LogInformation("GetCertificate Before Get Certificate from db");
            var certificate = await _certificateRepository.GetCertificate(request.Uln, request.StandardCode);

            _logger.LogInformation("GetCertificate Before Get Searching Organisation from db");
            var searchingOrganisation = await _organisationQueryRepository.GetByUkPrn(request.UkPrn);

            var allowedCertificateStatus = new string[] { CertificateStatus.Draft, CertificateStatus.Submitted, CertificateStatus.Printed, CertificateStatus.Reprint };

            if (certificate != null && searchingOrganisation != null && allowedCertificateStatus.Contains(certificate.Status))
            {
                var certData = JsonConvert.DeserializeObject <CertificateData>(certificate.CertificateData);

                if (string.Equals(certData.LearnerFamilyName, request.FamilyName, StringComparison.InvariantCultureIgnoreCase))
                {
                    certificate = await CertificateHelpers.ApplyStatusInformation(_certificateRepository, _contactQueryRepository, certificate);

                    if (!EpaOutcome.Pass.Equals(certData.EpaDetails?.LatestEpaOutcome, StringComparison.InvariantCultureIgnoreCase))
                    {
                        // As EPA has not passed, only give access to basic information & EPA Details
                        certificate = RedactCertificateInformation(certificate, true);
                    }

                    if (certificate.OrganisationId != searchingOrganisation.Id)
                    {
                        var providedStandards = await _standardRepository.GetEpaoRegisteredStandards(searchingOrganisation.EndPointAssessorOrganisationId, short.MaxValue, null);

                        if (providedStandards.PageOfResults.Any(s => s.StandardCode == certificate.StandardCode))
                        {
                            // Shared standard but not the EPAO who created the certificate
                            certificate = RedactCertificateInformation(certificate, false);
                        }
                        else
                        {
                            certificate = null;
                        }
                    }
                }
                else
                {
                    certificate = null;
                }
            }
            else
            {
                certificate = null;
            }

            return(certificate);
        }
Beispiel #10
0
        public GetBatchLearnerRequestValidator(IStringLocalizer <GetBatchLearnerRequestValidator> localiser, IOrganisationQueryRepository organisationQueryRepository, ILearnerRepository learnerRepository, ICertificateRepository certificateRepository, IStandardService standardService)
        {
            RuleFor(m => m.UkPrn).InclusiveBetween(10000000, 99999999).WithMessage("The UKPRN should contain exactly 8 numbers");

            RuleFor(m => m.FamilyName).NotEmpty().WithMessage("Provide apprentice family name");
            RuleFor(m => m.Standard).NotEmpty().WithMessage("Provide a Standard").DependentRules(() =>
            {
                RuleFor(m => m.Standard).CustomAsync(async(standard, context, cancellation) =>
                {
                    var standardVersion = await standardService.GetStandardVersionById(standard);

                    if (standardVersion is null)
                    {
                        context.AddFailure(new ValidationFailure("Standard", "Standard not found"));
                    }
                });
            });

            RuleFor(m => m.Uln).InclusiveBetween(1000000000, 9999999999).WithMessage("ULN should contain exactly 10 numbers").DependentRules(() =>
            {
                When(m => !string.IsNullOrEmpty(m.Standard) && !string.IsNullOrEmpty(m.FamilyName), () =>
                {
                    RuleFor(m => m).CustomAsync(async(m, context, cancellation) =>
                    {
                        var standard = await standardService.GetStandardVersionById(m.Standard);

                        if (standard != null)
                        {
                            var requestedLearner = await learnerRepository.Get(m.Uln, standard.LarsCode);
                            var sumbittingEpao   = await organisationQueryRepository.GetByUkPrn(m.UkPrn);

                            if (requestedLearner is null || !string.Equals(requestedLearner.FamilyName, m.FamilyName, StringComparison.InvariantCultureIgnoreCase))
                            {
                                context.AddFailure(new ValidationFailure("Uln", "ULN, FamilyName and Standard not found"));
                            }
                            else if (sumbittingEpao is null)
                            {
                                context.AddFailure(new ValidationFailure("UkPrn", "Specified UKPRN not found"));
                            }
                            else
                            {
                                var providedStandards = await standardService.GetEpaoRegisteredStandards(sumbittingEpao.EndPointAssessorOrganisationId);

                                if (!providedStandards.Any(s => s.StandardCode == standard.LarsCode))
                                {
                                    context.AddFailure(new ValidationFailure("StandardCode", "Your organisation is not approved to assess this Standard"));
                                }
                            }
                        }
                    });
        public UpdateBatchEpaRequestValidator(IStringLocalizer <BatchEpaRequestValidator> localiser, IOrganisationQueryRepository organisationQueryRepository, IIlrRepository ilrRepository, ICertificateRepository certificateRepository, IStandardService standardService)
        {
            Include(new BatchEpaRequestValidator(localiser, organisationQueryRepository, ilrRepository, standardService));

            RuleFor(m => m.EpaDetails.EpaReference).NotEmpty().WithMessage("Provide EPA reference").DependentRules(() =>
            {
                RuleFor(m => m).CustomAsync(async(m, context, cancellation) =>
                {
                    var existingCertificate = await certificateRepository.GetCertificate(m.Uln, m.StandardCode);
                    var sumbittingEpao      = await organisationQueryRepository.GetByUkPrn(m.UkPrn);

                    if (existingCertificate is null || !string.Equals(existingCertificate.CertificateReference, m.EpaDetails.EpaReference, StringComparison.InvariantCultureIgnoreCase))
                    {
                        context.AddFailure(new ValidationFailure("EpaReference", $"EPA not found"));
                    }
Beispiel #12
0
        private async Task <Certificate> GetCertificate(GetBatchCertificateRequest request)
        {
            _logger.LogInformation("GetCertificate Before Get Certificate from db");
            var certificate = await _certificateRepository.GetCertificate(request.Uln, request.StandardCode, request.FamilyName, request.IncludeLogs);

            _logger.LogInformation("GetCertificate Before Get Searching Organisation from db");
            var searchingOrganisation = await _organisationQueryRepository.GetByUkPrn(request.UkPrn);

            var allowedCertificateStatus = new[] { CertificateStatus.Draft, CertificateStatus.Submitted }.Concat(CertificateStatus.PrintProcessStatus);

            if (certificate == null || searchingOrganisation == null || !allowedCertificateStatus.Contains(certificate.Status))
            {
                return(null);
            }

            var certData = JsonConvert.DeserializeObject <CertificateData>(certificate.CertificateData);

            certificate = await CertificateHelpers.ApplyStatusInformation(_certificateRepository, _contactQueryRepository, certificate);

            if ((certificate.Status == CertificateStatus.Submitted || CertificateStatus.HasPrintProcessStatus(certificate.Status)) && certData.OverallGrade == CertificateGrade.Fail)
            {
                return(null);
            }
            else if (certificate.Status == CertificateStatus.Draft &&
                     EpaOutcome.Pass.Equals(certData.EpaDetails?.LatestEpaOutcome, StringComparison.InvariantCultureIgnoreCase) &&
                     certData.OverallGrade == null)
            {
                return(null);
            }

            if (certificate.OrganisationId != searchingOrganisation.Id)
            {
                var providedStandards = await _standardRepository.GetEpaoRegisteredStandards(searchingOrganisation.EndPointAssessorOrganisationId, int.MaxValue, 1);

                if (providedStandards.PageOfResults.Any(s => s.StandardCode == certificate.StandardCode))
                {
                    // Shared standard but not the EPAO who created the certificate
                    certificate = RedactCertificateInformation(certificate, false);
                }
                else
                {
                    certificate = null;
                }
            }

            return(certificate);
        }
Beispiel #13
0
        public UpdateBatchCertificateRequestValidator(IStringLocalizer <BatchCertificateRequestValidator> localiser, IOrganisationQueryRepository organisationQueryRepository, IIlrRepository ilrRepository, ICertificateRepository certificateRepository, IStandardService standardService)
        {
            Include(new BatchCertificateRequestValidator(localiser, organisationQueryRepository, ilrRepository, certificateRepository, standardService));

            RuleFor(m => m.CertificateReference).NotEmpty().WithMessage("Provide the certificate reference").DependentRules(() =>
            {
                // TODO: ON-2130 Consider in the future how to merge both create & update versions as the Cert will always exist due to EPA
                RuleFor(m => m).CustomAsync(async(m, context, cancellation) =>
                {
                    var existingCertificate = await certificateRepository.GetCertificate(m.Uln, m.StandardCode);
                    var sumbittingEpao      = await organisationQueryRepository.GetByUkPrn(m.UkPrn);

                    if (existingCertificate is null || !string.Equals(existingCertificate.CertificateReference, m.CertificateReference, StringComparison.InvariantCultureIgnoreCase) ||
                        existingCertificate.Status == CertificateStatus.Deleted)
                    {
                        context.AddFailure(new ValidationFailure("CertificateReference", $"Certificate not found"));
                    }
Beispiel #14
0
        public async Task <Certificate> Handle(StartCertificateRequest request, CancellationToken cancellationToken)
        {
            _logger.LogDebug($"Starting new certificate for EPAO UkPrn:{request.UkPrn}");
            var organisation = await _organisationQueryRepository.GetByUkPrn(request.UkPrn);

            var certificate = await _certificateRepository.GetCertificate(request.Uln, request.StandardCode);

            if (certificate == null)
            {
                certificate = await CreateNewCertificate(request, organisation);
            }
            else
            {
                certificate = await UpdateExistingCertificate(request, organisation, certificate);
            }

            return(certificate);
        }
        public async Task <IActionResult> SearchOrganisation(int ukprn)
        {
            _logger.LogInformation($"Received Search for an Organisation Request using ukprn {ukprn}");

            var result = _ukPrnValidator.Validate(ukprn);

            if (!result.IsValid)
            {
                throw new BadRequestException(result.Errors[0].ErrorMessage);
            }

            var organisation = Mapper.Map <OrganisationResponse>(await _organisationQueryRepository.GetByUkPrn(ukprn));

            if (organisation == null)
            {
                var ex = new ResourceNotFoundException(
                    string.Format(_localizer[ResourceMessageName.NoAssesmentProviderFound].Value, ukprn));
                throw ex;
            }

            return(Ok(organisation));
        }
Beispiel #16
0
        public async Task <ActionResult <ApiValidationResult> > ValidateUkPrn(int q)
        {
            // false if on epao register already.
            var epaOrg = await _organisationQueryRepository.GetByUkPrn(q);

            if (epaOrg != null)
            {
                return(new ApiValidationResult {
                    IsValid = false, ErrorMessages = new List <KeyValuePair <string, string> > {
                        new KeyValuePair <string, string>("", "UKPRN provided already in use")
                    }
                });
            }

            // starts with 9, allow
            if (q.ToString().StartsWith("9"))
            {
                return new ApiValidationResult {
                           IsValid = true
                }
            }
            ;

            var ukrlpResult = await _roatpApiClient.SearchOrganisationInUkrlp(q);

            if (ukrlpResult == null || !ukrlpResult.Any())
            {
                return(new ApiValidationResult {
                    IsValid = false, ErrorMessages = new List <KeyValuePair <string, string> > {
                        new KeyValuePair <string, string>("", "UKPRN is unknown")
                    }
                });
            }

            return(new ApiValidationResult {
                IsValid = true
            });
        }
    }
Beispiel #17
0
        private async Task <LearnerDetailForExternalApi> GetLearnerDetails(GetBatchLearnerRequest request, Standard standard, Certificate certFromRepository)
        {
            LearnerDetailForExternalApi learnerDetail = null;

            var certData = GetCertificateDataFromCertificate(certFromRepository);

            if (standard != null)
            {
                var learner = await _learnerRepository.Get(request.Uln, standard.LarsCode);

                if (learner != null)
                {
                    var epao = await _organisationRepository.GetByUkPrn(learner.UkPrn);

                    learnerDetail = new LearnerDetailForExternalApi()
                    {
                        Uln                            = learner.Uln,
                        GivenNames                     = learner.GivenNames,
                        FamilyName                     = learner.FamilyName,
                        LearnerStartDate               = learner.LearnStartDate,
                        LearnerReferenceNumber         = learner.LearnRefNumber,
                        PlannedEndDate                 = learner.PlannedEndDate,
                        CompletionStatus               = learner.CompletionStatus,
                        Standard                       = standard,
                        EndPointAssessorOrganisationId = epao?.EndPointAssessorOrganisationId ?? learner.EpaOrgId,
                        UkPrn                          = epao?.EndPointAssessorUkprn ?? learner.UkPrn,
                        OrganisationName               = epao?.EndPointAssessorName ?? "Unknown",
                        Version                        = certData?.Version,
                        CourseOption                   = certData?.CourseOption
                    };
                }
                else
                {
                    _logger.LogError($"Could not find learner for ULN {request.Uln} and StandardCode {standard.LarsCode}");
                }
            }

            return(learnerDetail);
        }
        public GetBatchCertificateRequestValidator(IStringLocalizer <GetBatchCertificateRequestValidator> localiser, IOrganisationQueryRepository organisationQueryRepository, IIlrRepository ilrRepository, ICertificateRepository certificateRepository, IStandardService standardService)
        {
            RuleFor(m => m.UkPrn).InclusiveBetween(10000000, 99999999).WithMessage("The UKPRN should contain exactly 8 numbers");

            RuleFor(m => m.FamilyName).NotEmpty().WithMessage("Provide apprentice family name");
            RuleFor(m => m.StandardCode).GreaterThan(0).WithMessage("Provide a valid Standard").DependentRules(() =>
            {
                RuleFor(m => m).CustomAsync(async(m, context, cancellation) =>
                {
                    if (!string.IsNullOrEmpty(m.StandardReference))
                    {
                        var collatedStandard = await standardService.GetStandard(m.StandardReference);
                        if (m.StandardCode != collatedStandard?.StandardId)
                        {
                            context.AddFailure("StandardReference and StandardCode must be for the same Standard");
                        }
                    }
                });
            });

            RuleFor(m => m.Uln).InclusiveBetween(1000000000, 9999999999).WithMessage("ULN should contain exactly 10 numbers").DependentRules(() =>
            {
                When(m => m.StandardCode > 0 && !string.IsNullOrEmpty(m.FamilyName), () =>
                {
                    RuleFor(m => m).CustomAsync(async(m, context, cancellation) =>
                    {
                        // NOTE: Currently we're making the Certificate & ILR record both mandatory
                        var requestedIlr   = await ilrRepository.Get(m.Uln, m.StandardCode);
                        var sumbittingEpao = await organisationQueryRepository.GetByUkPrn(m.UkPrn);

                        if (requestedIlr is null || !string.Equals(requestedIlr.FamilyName, m.FamilyName, StringComparison.InvariantCultureIgnoreCase))
                        {
                            context.AddFailure(new ValidationFailure("Uln", "ULN, FamilyName and Standard not found"));
                        }
                        else if (sumbittingEpao is null)
                        {
                            context.AddFailure(new ValidationFailure("UkPrn", "Specified UKPRN not found"));
                        }
                        else
                        {
                            var providedStandards = await standardService.GetEpaoRegisteredStandards(sumbittingEpao.EndPointAssessorOrganisationId);

                            if (!providedStandards.Any(s => s.StandardCode == m.StandardCode))
                            {
                                context.AddFailure(new ValidationFailure("StandardCode", "Your organisation is not approved to assess this Standard"));
                            }
                        }
                    });

                    RuleFor(m => m).CustomAsync(async(m, context, cancellation) =>
                    {
                        var existingCertificate = await certificateRepository.GetCertificate(m.Uln, m.StandardCode);

                        if (existingCertificate is null)
                        {
                            // TODO: FUTURE WORK - ON-2130 Do Alan's Certificate Search THEN the ILR Search (which may be the validation down below)
                        }
                        else
                        {
                            var certData = JsonConvert.DeserializeObject <CertificateData>(existingCertificate.CertificateData ?? "{}");

                            if (!certData.LearnerFamilyName.Equals(m.FamilyName, StringComparison.InvariantCultureIgnoreCase))
                            {
                                context.AddFailure(new ValidationFailure("FamilyName", $"Invalid family name"));
                            }
                            else if (!EpaOutcome.Pass.Equals(certData.EpaDetails?.LatestEpaOutcome, StringComparison.InvariantCultureIgnoreCase))
                            {
                                context.AddFailure(new ValidationFailure("Uln", $"Latest EPA Outcome has not passed"));
                            }
                        }
                    });
                });
Beispiel #19
0
        public BatchCertificateRequestValidator(
            IStringLocalizer <BatchCertificateRequestValidator> localiser,
            IOrganisationQueryRepository organisationQueryRepository,
            IIlrRepository ilrRepository,
            IStandardService standardService)
        {
            RuleFor(m => m.UkPrn).InclusiveBetween(10000000, 99999999).WithMessage("The UKPRN should contain exactly 8 numbers");

            RuleFor(m => m.FamilyName).NotEmpty().WithMessage("Provide apprentice family name");
            RuleFor(m => m.StandardCode).GreaterThan(0).WithMessage("Provide a valid Standard").DependentRules(() =>
            {
                RuleFor(m => m).CustomAsync(async(m, context, cancellation) =>
                {
                    bool validateCourseOption = true;

                    var collatedStandard = await standardService.GetStandard(m.StandardCode);
                    if (!string.IsNullOrEmpty(m.StandardReference))
                    {
                        if (m.StandardReference != collatedStandard?.ReferenceNumber)
                        {
                            validateCourseOption = false;
                            context.AddFailure("StandardReference and StandardCode must be for the same Standard");
                        }
                    }

                    // NOTE: This is not a nice way to do this BUT we cannot use another DependantRules()
                    if (validateCourseOption)
                    {
                        if (!collatedStandard.Options.Any() && !string.IsNullOrEmpty(m.CertificateData?.CourseOption))
                        {
                            context.AddFailure(new ValidationFailure("CourseOption", $"No course option available for this Standard. Must be empty"));
                        }
                        else if (collatedStandard.Options.Any() && !collatedStandard.Options.Any(o => o.Equals(m.CertificateData?.CourseOption, StringComparison.InvariantCultureIgnoreCase)))
                        {
                            string courseOptionsString = string.Join(", ", collatedStandard.Options);
                            context.AddFailure(new ValidationFailure("CourseOption", $"Invalid course option for this Standard. Must be one of the following: {courseOptionsString}"));
                        }
                    }
                });
            });

            RuleFor(m => m.Uln).InclusiveBetween(1000000000, 9999999999).WithMessage("ULN should contain exactly 10 numbers").DependentRules(() =>
            {
                When(m => m.StandardCode > 0 && !string.IsNullOrEmpty(m.FamilyName), () =>
                {
                    RuleFor(m => m).CustomAsync(async(m, context, canellation) =>
                    {
                        var requestedIlr   = await ilrRepository.Get(m.Uln, m.StandardCode);
                        var sumbittingEpao = await organisationQueryRepository.GetByUkPrn(m.UkPrn);

                        if (requestedIlr is null || !string.Equals(requestedIlr.FamilyName, m.FamilyName, StringComparison.InvariantCultureIgnoreCase))
                        {
                            context.AddFailure(new ValidationFailure("Uln", "ULN, FamilyName and Standard not found."));
                        }
                        else if (sumbittingEpao is null)
                        {
                            context.AddFailure(new ValidationFailure("UkPrn", "Specified UKPRN not found"));
                        }
                        else
                        {
                            var providedStandards = await standardService.GetEpaoRegisteredStandards(sumbittingEpao.EndPointAssessorOrganisationId);

                            if (!providedStandards.Any(s => s.StandardCode == m.StandardCode))
                            {
                                context.AddFailure(new ValidationFailure("StandardCode", "Your organisation is not approved to assess this Standard"));
                            }
                        }
                    });
                });
Beispiel #20
0
        public CreateBatchCertificateRequestValidator(
            IStringLocalizer <BatchCertificateRequestValidator> localiser,
            IOrganisationQueryRepository organisationQueryRepository,
            ILearnerRepository learnerRepository,
            ICertificateRepository certificateRepository,
            IStandardService standardService)
        {
            Include(new BatchCertificateRequestValidator(localiser, organisationQueryRepository, learnerRepository, standardService));

            RuleFor(m => m.CertificateReference).Empty().WithMessage("Certificate reference must be empty").DependentRules(() =>
            {
                RuleFor(m => m).CustomAsync(async(m, context, cancellation) =>
                {
                    var existingCertificate = await certificateRepository.GetCertificate(m.Uln, m.StandardCode);
                    var sumbittingEpao      = await organisationQueryRepository.GetByUkPrn(m.UkPrn);
                    var learnerDetails      = await learnerRepository.Get(m.Uln, m.StandardCode);

                    if (existingCertificate != null && existingCertificate.Status != CertificateStatus.Deleted)
                    {
                        var certData = JsonConvert.DeserializeObject <CertificateData>(existingCertificate.CertificateData);

                        if (sumbittingEpao?.Id != existingCertificate.OrganisationId)
                        {
                            context.AddFailure(new ValidationFailure("CertificateData", $"Your organisation is not the creator of the EPA"));
                        }
                        else if (existingCertificate.Status == CertificateStatus.Draft)
                        {
                            if (!string.IsNullOrEmpty(certData.OverallGrade))
                            {
                                context.AddFailure(new ValidationFailure("CertificateData", $"Certificate already exists: {existingCertificate.CertificateReference}"));
                            }
                        }
                        else if (existingCertificate.Status == CertificateStatus.Submitted && !string.IsNullOrWhiteSpace(certData.OverallGrade) && certData.OverallGrade.Equals(CertificateGrade.Fail, StringComparison.OrdinalIgnoreCase))
                        {
                            // A submitted fail can be re-created
                        }
                        else
                        {
                            context.AddFailure(new ValidationFailure("CertificateData", $"Certificate already exists: {existingCertificate.CertificateReference}"));
                        }
                    }

                    if (learnerDetails != null)
                    {
                        if (learnerDetails.CompletionStatus == (int)CompletionStatus.Withdrawn)
                        {
                            context.AddFailure(new ValidationFailure("LearnerDetails", "Cannot find the apprentice details"));
                        }
                        else if (learnerDetails.CompletionStatus == (int)CompletionStatus.TemporarilyWithdrawn)
                        {
                            context.AddFailure(new ValidationFailure("LearnerDetails", "Cannot find the apprentice details"));
                        }

                        // SV-1253 additional validation to check version and option
                        if (learnerDetails.VersionConfirmed && !string.IsNullOrWhiteSpace(learnerDetails.Version) && !string.IsNullOrWhiteSpace(m.CertificateData.Version))
                        {
                            if (learnerDetails.Version.Trim().ToUpperInvariant() != m.CertificateData.Version.Trim().ToUpperInvariant())
                            {
                                context.AddFailure(new ValidationFailure("LearnerDetails", "Incorrect version for learner"));
                            }
                        }
                        if (!string.IsNullOrWhiteSpace(learnerDetails.CourseOption) && !string.IsNullOrWhiteSpace(m.CertificateData.CourseOption))
                        {
                            if (learnerDetails.CourseOption.Trim().ToUpperInvariant() != m.CertificateData.CourseOption.Trim().ToUpperInvariant())
                            {
                                context.AddFailure(new ValidationFailure("LearnerDetails", "Incorrect course option for learner"));
                            }
                        }
                    }
                    else
                    {
                        context.AddFailure(new ValidationFailure("LearnerDetails", $"Learner details for ULN: {m.Uln} not found"));
                    }
                });
            });
        }
Beispiel #21
0
        public BatchCertificateRequestValidator(
            IStringLocalizer <BatchCertificateRequestValidator> localiser,
            IOrganisationQueryRepository organisationQueryRepository,
            ILearnerRepository learnerRepository,
            IStandardService standardService)
        {
            bool invalidVersionOrStandardMismatch = false;

            RuleFor(m => m.UkPrn).InclusiveBetween(10000000, 99999999).WithMessage("The UKPRN should contain exactly 8 numbers");

            RuleFor(m => m.FamilyName).NotEmpty().WithMessage("Provide apprentice family name");
            RuleFor(m => m.StandardCode).GreaterThan(0).WithMessage("Provide a valid Standard").DependentRules(() =>
            {
                RuleFor(m => m).CustomAsync(async(m, context, cancellation) =>
                {
                    var standard = await standardService.GetStandardVersionById(m.StandardCode.ToString(), m.CertificateData.Version);
                    if (!string.IsNullOrEmpty(m.StandardReference))
                    {
                        if (m.StandardReference != standard?.IfateReferenceNumber)
                        {
                            invalidVersionOrStandardMismatch = true;
                            context.AddFailure("StandardReference and StandardCode must be for the same Standard");
                        }
                    }

                    if (!invalidVersionOrStandardMismatch && standard != null)
                    {
                        var standardOptions  = await standardService.GetStandardOptionsByStandardId(standard.StandardUId);
                        var noOptions        = standardOptions == null || !standardOptions.HasOptions();
                        var hasOptions       = standardOptions != null && standardOptions.HasOptions();
                        var requestedLearner = await learnerRepository.Get(m.Uln, m.StandardCode);
                        var courseOption     = m.CertificateData?.CourseOption;
                        if (null != requestedLearner && !string.IsNullOrWhiteSpace(requestedLearner.CourseOption))
                        {
                            courseOption = requestedLearner.CourseOption;
                        }
                        if (noOptions && !string.IsNullOrEmpty(m.CertificateData?.CourseOption))
                        {
                            context.AddFailure(new ValidationFailure("CourseOption", $"No course option available for this Standard and version. Must be empty"));
                        }
                        else if (hasOptions && !standardOptions.CourseOption.Any(o => o.Equals(courseOption, StringComparison.InvariantCultureIgnoreCase)))
                        {
                            string courseOptionsString = string.Join(", ", standardOptions.CourseOption);
                            context.AddFailure(new ValidationFailure("CourseOption", $"Invalid course option for this Standard and version. Must be one of the following: {courseOptionsString} where {courseOptionsString} depends on the standard code, and can be obtained with GET /api/v1/standard/options/{standard.LarsCode}/{standard.Version}"));
                        }
                    }
                });
            });

            When(m => !string.IsNullOrWhiteSpace(m.CertificateData.Version), () =>
            {
                RuleFor(m => m).Custom((m, context) =>
                {
                    // If Version specified but StandardUId not populated, must be invalid version
                    // Otherwise we assume the auto-select process succeeded.
                    if (string.IsNullOrWhiteSpace(m.StandardUId) && !invalidVersionOrStandardMismatch)
                    {
                        invalidVersionOrStandardMismatch = true;
                        context.AddFailure(new ValidationFailure("Standard", "Invalid version for Standard"));
                    }
                });
            });

            RuleFor(m => m.Uln).InclusiveBetween(1000000000, 9999999999).WithMessage("ULN should contain exactly 10 numbers").DependentRules(() =>
            {
                When(m => m.StandardCode > 0 && !string.IsNullOrEmpty(m.FamilyName), () =>
                {
                    RuleFor(m => m).CustomAsync(async(m, context, canellation) =>
                    {
                        var requestedLearner = await learnerRepository.Get(m.Uln, m.StandardCode);
                        var submittingEpao   = await organisationQueryRepository.GetByUkPrn(m.UkPrn);

                        if (requestedLearner is null || !string.Equals(requestedLearner.FamilyName, m.FamilyName, StringComparison.InvariantCultureIgnoreCase))
                        {
                            context.AddFailure(new ValidationFailure("Uln", "ULN, FamilyName and Standard not found."));
                        }
                        else if (submittingEpao is null)
                        {
                            context.AddFailure(new ValidationFailure("UkPrn", "Specified UKPRN not found"));
                        }
                        else
                        {
                            var providedStandardVersions = await standardService.GetEPAORegisteredStandardVersions(submittingEpao.EndPointAssessorOrganisationId, m.StandardCode);

                            if (!providedStandardVersions.Any())
                            {
                                context.AddFailure(new ValidationFailure("StandardCode", "Your organisation is not approved to assess this Standard"));
                            }
                            else if (!(invalidVersionOrStandardMismatch || providedStandardVersions.Any(v => v.Version.Equals(m.CertificateData.Version, StringComparison.InvariantCultureIgnoreCase))))
                            {
                                context.AddFailure(new ValidationFailure("Version", $"Your organisation is not approved to assess this Standard Version: {m.CertificateData.Version}"));
                            }
                        }
                    });
                });