Ejemplo n.º 1
0
        private Func <Provider, string> GetProviderFieldForGrouping(OrganisationGroupTypeIdentifier identifierType, OrganisationGroupTypeCode organisationGroupTypeCode, GroupingReason groupingReason, PaymentOrganisationSource paymentOrganisationSource)
        {
            if (groupingReason.IsForProviderPayment())
            {
                if (paymentOrganisationSource == PaymentOrganisationSource.PaymentOrganisationAsProvider)
                {
                    // If the grouping reason is for payment, then the organisation identifier needs to be returned as a UKPRN, but grouped on the type code
                    switch (organisationGroupTypeCode)
                    {
                    case OrganisationGroupTypeCode.AcademyTrust:
                        return(c => c.TrustCode);

                    case OrganisationGroupTypeCode.LocalAuthority:
                        return(c => c.LACode);

                    case OrganisationGroupTypeCode.Provider:
                        return(c => c.UKPRN);

                    default:
                        throw new InvalidOperationException($"Unknown organisation group type code to select for identifer for payment. '{organisationGroupTypeCode}'");
                    }
                }
                else if (paymentOrganisationSource == PaymentOrganisationSource.PaymentOrganisationFields)
                {
                    return(p => p.PaymentOrganisationIdentifier);
                }
                else
                {
                    throw new InvalidOperationException($"Unknown paymentOrganisationSource '{paymentOrganisationSource}'");
                }
            }
            else if (groupingReason == GroupingReason.Information)
            {
                // TODO: Map all fields required
                switch (identifierType)
                {
                case OrganisationGroupTypeIdentifier.UKPRN:
                    return(c => c.UKPRN);

                case OrganisationGroupTypeIdentifier.AcademyTrustCode:
                    return(c => c.TrustCode);

                case OrganisationGroupTypeIdentifier.ParliamentaryConstituencyCode:
                    return(c => c.ParliamentaryConstituencyCode);

                case OrganisationGroupTypeIdentifier.MiddleSuperOutputAreaCode:
                    return(c => c.MiddleSuperOutputAreaCode);

                case OrganisationGroupTypeIdentifier.CensusWardCode:
                    return(c => c.CensusWardCode);

                case OrganisationGroupTypeIdentifier.DistrictCode:
                    return(c => c.DistrictCode);

                case OrganisationGroupTypeIdentifier.GovernmentOfficeRegionCode:
                    return(c => c.GovernmentOfficeRegionCode);

                case OrganisationGroupTypeIdentifier.LowerSuperOutputAreaCode:
                    return(c => c.LowerSuperOutputAreaCode);

                case OrganisationGroupTypeIdentifier.WardCode:
                    return(c => c.WardCode);

                case OrganisationGroupTypeIdentifier.RscRegionCode:
                    return(c => c.RscRegionCode);

                case OrganisationGroupTypeIdentifier.CountryCode:
                    return(c => c.CountryCode);

                case OrganisationGroupTypeIdentifier.LACode:
                    return(c => c.LACode);

                case OrganisationGroupTypeIdentifier.LocalAuthorityClassificationTypeCode:
                    return(c => c.LocalGovernmentGroupTypeCode);
                }
            }

            throw new Exception("Unknown OrganisationGroupTypeIdentifier for provider ID");
        }
Ejemplo n.º 2
0
        public FundingConfigurationBuilder WithPaymentOrganisationSource(PaymentOrganisationSource paymentOrganisationSource)
        {
            _config.PaymentOrganisationSource = paymentOrganisationSource;

            return(this);
        }
Ejemplo n.º 3
0
        public async Task <IEnumerable <OrganisationGroupResult> > GenerateOrganisationGroup(
            IEnumerable <OrganisationGroupingConfiguration> organisationGroupingConfigurations,
            ProviderSource providerSource,
            PaymentOrganisationSource paymentOrganisationSource,
            IEnumerable <Provider> scopedProviders,
            string providerVersionId,
            int?providerSnapshotId = null)
        {
            Guard.ArgumentNotNull(organisationGroupingConfigurations, nameof(organisationGroupingConfigurations));
            Guard.ArgumentNotNull(providerSource, nameof(providerSource));
            Guard.ArgumentNotNull(paymentOrganisationSource, nameof(paymentOrganisationSource));
            Guard.ArgumentNotNull(scopedProviders, nameof(scopedProviders));
            Guard.IsNullOrWhiteSpace(providerVersionId, nameof(providerVersionId));

            List <OrganisationGroupResult> results = new List <OrganisationGroupResult>();

            Dictionary <string, FdzPaymentOrganisation> paymentOrganisations = new Dictionary <string, FdzPaymentOrganisation>();

            if (providerSource == ProviderSource.FDZ &&
                organisationGroupingConfigurations.Any(g => g.GroupingReason == GroupingReason.Payment ||
                                                       g.GroupingReason == GroupingReason.Contracting ||
                                                       g.GroupingReason == GroupingReason.Indicative))
            {
                if (!providerSnapshotId.HasValue)
                {
                    throw new InvalidOperationException("No provider snapshot ID provided, but it is required fto lookup Payment Organisations from FDZ");
                }

                ApiResponse <IEnumerable <FdzPaymentOrganisation> > paymentOrganisationsResponse = await _fundingDataZoneApiClient.GetAllOrganisations(providerSnapshotId.Value);

                if (paymentOrganisationsResponse.StatusCode == System.Net.HttpStatusCode.OK && paymentOrganisationsResponse.Content != null)
                {
                    foreach (FdzPaymentOrganisation fdzPaymentOrganisation in paymentOrganisationsResponse.Content)
                    {
                        if (paymentOrganisations.ContainsKey(fdzPaymentOrganisation.Ukprn))
                        {
                            throw new Exception($"The payment organisation group: '{fdzPaymentOrganisation.Ukprn}' needs to be unique for provider snapshot ID '{providerSnapshotId}'.");
                        }
                        else
                        {
                            paymentOrganisations.Add(fdzPaymentOrganisation.Ukprn, fdzPaymentOrganisation);
                        }
                    }
                }
                else
                {
                    throw new InvalidOperationException($"Unable to retreive payment organisations from provider snapshot ID of {providerSnapshotId}");
                }
            }

            foreach (OrganisationGroupingConfiguration grouping in organisationGroupingConfigurations)
            {
                // Get the provider attribute required to group
                Func <Provider, string> providerFilterAttribute = GetProviderFieldForGrouping(
                    grouping.GroupTypeIdentifier, grouping.OrganisationGroupTypeCode, grouping.GroupingReason, paymentOrganisationSource);

                // Filter providers based on provider type and subtypes
                IEnumerable <Provider> providersForGroup = grouping.ProviderTypeMatch.IsNullOrEmpty() ? scopedProviders : scopedProviders.Where(_ => _providerFilter.ShouldIncludeProvider(_, grouping.ProviderTypeMatch));

                // Filter providers based on provider status
                providersForGroup = grouping.ProviderStatus.IsNullOrEmpty() ? providersForGroup : providersForGroup.Where(_ => _providerFilter.ShouldIncludeProvider(_, grouping.ProviderStatus));

                // Group providers by the fields and discard any providers with null values for that field
                IEnumerable <IGrouping <string, Provider> > groupedProviders = providersForGroup.GroupBy(providerFilterAttribute);

                // Common values for all groups
                Enums.OrganisationGroupTypeClassification organisationGroupTypeClassification = grouping.GroupingReason.IsForProviderPayment() ? Enums.OrganisationGroupTypeClassification.LegalEntity : Enums.OrganisationGroupTypeClassification.GeographicalBoundary;
                Enums.OrganisationGroupTypeCode           organisationGroupTypeCode           = grouping.OrganisationGroupTypeCode.AsMatchingEnum <Enums.OrganisationGroupTypeCode>();

                // Generate Organisation Group results based on the grouped providers
                foreach (IGrouping <string, Provider> providerGrouping in groupedProviders)
                {
                    // Ignore providers without the matching data in the key
                    if (string.IsNullOrWhiteSpace(providerGrouping.Key))
                    {
                        continue;
                    }

                    TargetOrganisationGroup targetOrganisationGroup = null;

                    if (paymentOrganisationSource == PaymentOrganisationSource.PaymentOrganisationFields &&
                        grouping.GroupingReason.IsForProviderPayment())
                    {
                        IEnumerable <OrganisationIdentifier> identifiers;

                        // lookup alternative identifier and name from FDZ's PaymentOrganisation table via FDZ service
                        if (providerSource == ProviderSource.FDZ &&
                            paymentOrganisations.TryGetValue(providerGrouping.Key, out FdzPaymentOrganisation fdzPaymentOrganisation))
                        {
                            identifiers = GetIdentifiers(fdzPaymentOrganisation);
                        }
                        else
                        {
                            identifiers = Array.Empty <OrganisationIdentifier>();
                        }

                        // Will use providerGrouping.Key as the identifier of the PaymentOrganisation
                        targetOrganisationGroup = new TargetOrganisationGroup()
                        {
                            Identifier  = grouping.OrganisationGroupTypeCode == OrganisationGroupTypeCode.Provider ? providerGrouping.First().ProviderId : providerGrouping.First().PaymentOrganisationIdentifier,
                            Name        = grouping.OrganisationGroupTypeCode == OrganisationGroupTypeCode.Provider ? providerGrouping.First().Name : providerGrouping.First().PaymentOrganisationName,
                            Identifiers = identifiers,
                        };
                    }
                    else if (paymentOrganisationSource == PaymentOrganisationSource.PaymentOrganisationAsProvider ||
                             (paymentOrganisationSource == PaymentOrganisationSource.PaymentOrganisationFields &&
                              !grouping.GroupingReason.IsForProviderPayment())
                             )
                    {
                        targetOrganisationGroup = await ObtainTargetOrganisationGroupFromProviderData(providerVersionId, grouping, providerGrouping);
                    }


                    if (targetOrganisationGroup == null)
                    {
                        // TODO: improve logging
                        throw new Exception($"Target Organisation Group could not be found for identifier '{providerGrouping.Key}'");
                    }

                    OrganisationGroupResult organisationGroupResult = new OrganisationGroupResult()
                    {
                        GroupTypeClassification = organisationGroupTypeClassification,
                        GroupTypeCode           = organisationGroupTypeCode,
                        GroupTypeIdentifier     = grouping.GroupTypeIdentifier.AsMatchingEnum <Enums.OrganisationGroupTypeIdentifier>(),
                        GroupReason             = grouping.GroupingReason.AsMatchingEnum <Enums.OrganisationGroupingReason>(),
                        IdentifierValue         = targetOrganisationGroup.Identifier,
                        Name           = targetOrganisationGroup.Name,
                        Identifiers    = targetOrganisationGroup.Identifiers,
                        SearchableName = Sanitiser.SanitiseName(targetOrganisationGroup.Name),
                        Providers      = providerGrouping,
                    };

                    results.Add(organisationGroupResult);
                }
            }

            return(results);
        }