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"); }
public FundingConfigurationBuilder WithPaymentOrganisationSource(PaymentOrganisationSource paymentOrganisationSource) { _config.PaymentOrganisationSource = paymentOrganisationSource; return(this); }
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); }