public async Task <IEnumerable <OrganisationGroupResult> > GenerateOrganisationGroup(FundingConfiguration fundingConfiguration, IEnumerable <Provider> scopedProviders, string providerVersionId) { Guard.ArgumentNotNull(fundingConfiguration, nameof(fundingConfiguration)); Guard.ArgumentNotNull(scopedProviders, nameof(scopedProviders)); Guard.IsNullOrWhiteSpace(providerVersionId, nameof(providerVersionId)); List <OrganisationGroupResult> results = new List <OrganisationGroupResult>(); foreach (OrganisationGroupingConfiguration grouping in fundingConfiguration.OrganisationGroupings) { // Get the provider attribute required to group Func <Provider, string> providerFilterAttribute = GetProviderFieldForGrouping(grouping.GroupTypeIdentifier, grouping.OrganisationGroupTypeCode, grouping.GroupingReason); // Filter providers based on provider type and subtypes IEnumerable <Provider> providersForGroup = grouping.ProviderTypeMatch.IsNullOrEmpty() ? scopedProviders : scopedProviders.Where(_ => ShouldIncludeProvider(_, grouping.ProviderTypeMatch)); // 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 == GroupingReason.Payment ? 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; OrganisationGroupLookupParameters organisationGroupLookupParameters = new OrganisationGroupLookupParameters { IdentifierValue = providerGrouping.Key, OrganisationGroupTypeCode = grouping.OrganisationGroupTypeCode, ProviderVersionId = providerVersionId, GroupTypeIdentifier = grouping.GroupTypeIdentifier }; targetOrganisationGroup = await _organisationGroupTargetProviderLookup.GetTargetProviderDetails(organisationGroupLookupParameters, grouping.GroupingReason, 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 = GenerateSearchableName(targetOrganisationGroup.Name), Providers = providerGrouping, }; results.Add(organisationGroupResult); } } return(results); }
public async Task <IEnumerable <OrganisationGroupResult> > GenerateOrganisationGroup( FundingConfiguration fundingConfiguration, IEnumerable <Provider> scopedProviders, string providerVersionId, int?providerSnapshotId = null) { Guard.ArgumentNotNull(fundingConfiguration, nameof(fundingConfiguration)); 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 (fundingConfiguration.ProviderSource == ProviderSource.FDZ && fundingConfiguration.OrganisationGroupings.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 fundingConfiguration.OrganisationGroupings) { // Get the provider attribute required to group Func <Provider, string> providerFilterAttribute = GetProviderFieldForGrouping(grouping.GroupTypeIdentifier, grouping.OrganisationGroupTypeCode, grouping.GroupingReason, fundingConfiguration.PaymentOrganisationSource); // Filter providers based on provider type and subtypes IEnumerable <Provider> providersForGroup = grouping.ProviderTypeMatch.IsNullOrEmpty() ? scopedProviders : scopedProviders.Where(_ => ShouldIncludeProvider(_, grouping.ProviderTypeMatch)); // Filter providers based on provider status providersForGroup = grouping.ProviderStatus.IsNullOrEmpty() ? providersForGroup : providersForGroup.Where(_ => 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 (fundingConfiguration.PaymentOrganisationSource == PaymentOrganisationSource.PaymentOrganisationFields && grouping.GroupingReason.IsForProviderPayment()) { IEnumerable <OrganisationIdentifier> identifiers; // lookup alternative identifier and name from FDZ's PaymentOrganisation table via FDZ service if (fundingConfiguration.ProviderSource == ProviderSource.FDZ && paymentOrganisations.TryGetValue(providerGrouping.Key, out FdzPaymentOrganisation fdzPaymentOrganisation)) { identifiers = GetIdentifiers(fdzPaymentOrganisation); } else { identifiers = new OrganisationIdentifier[0]; } // Will use providerGrouping.Key as the identifier of the PaymentOrganisation targetOrganisationGroup = new TargetOrganisationGroup() { Identifier = providerGrouping.First().PaymentOrganisationIdentifier, Name = providerGrouping.First().PaymentOrganisationName, Identifiers = identifiers, }; } else if (fundingConfiguration.PaymentOrganisationSource == PaymentOrganisationSource.PaymentOrganisationAsProvider || (fundingConfiguration.PaymentOrganisationSource == PaymentOrganisationSource.PaymentOrganisationFields && !grouping.GroupingReason.IsForProviderPayment()) ) { targetOrganisationGroup = await ObtainTargetOrganisationGroupFromProviderData(fundingConfiguration, providerVersionId, grouping, providerGrouping, targetOrganisationGroup); } 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); }