From 4007e5c8dffafae75835d91904ef64090f95fbcd Mon Sep 17 00:00:00 2001 From: Tayyab Fayyaz Janjua Date: Fri, 11 Oct 2024 10:51:56 +0200 Subject: [PATCH 1/3] chore(partnerNetwork): Get data from partner network pool by portal backend (#61) Ref: #1079 --- .../IPartnerNetworkBusinessLogic.cs | 13 + .../PartnerNetworkBusinessLogic.cs | 143 +++++++- .../Controllers/PartnerNetworkController.cs | 22 ++ .../Models/PartnerNetworkRequest.cs | 26 ++ .../Models/PartnerNetworkResponse.cs | 169 +++++++++ .../Administration.Service/Program.cs | 3 + .../Administration.Service/appsettings.json | 1 + src/externalsystems/Bpdm.Library/BpnAccess.cs | 33 ++ .../Bpdm.Library/IBpnAccess.cs | 2 + .../Models/BpdmPartnerNetworkData.cs | 31 ++ .../Models/BpdmPartnerNetworkRequest.cs | 28 ++ .../PartnerNetworkBusinessLogicTests.cs | 98 +++++- .../PartnerNetworkControllerTest.cs | 21 ++ .../Bpdm.Library/BPNAccessTest.cs | 323 ++++++++++++++++++ 14 files changed, 911 insertions(+), 2 deletions(-) create mode 100644 src/administration/Administration.Service/Models/PartnerNetworkRequest.cs create mode 100644 src/administration/Administration.Service/Models/PartnerNetworkResponse.cs create mode 100644 src/externalsystems/Bpdm.Library/Models/BpdmPartnerNetworkData.cs create mode 100644 src/externalsystems/Bpdm.Library/Models/BpdmPartnerNetworkRequest.cs diff --git a/src/administration/Administration.Service/BusinessLogic/IPartnerNetworkBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/IPartnerNetworkBusinessLogic.cs index e4160be613..c3500751cf 100644 --- a/src/administration/Administration.Service/BusinessLogic/IPartnerNetworkBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/IPartnerNetworkBusinessLogic.cs @@ -18,6 +18,8 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models; + namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLogic { public interface IPartnerNetworkBusinessLogic @@ -27,5 +29,16 @@ public interface IPartnerNetworkBusinessLogic /// /// Ids of BPN IAsyncEnumerable GetAllMemberCompaniesBPNAsync(IEnumerable? bpnIds); + + /// + /// Gets partner network data from BPN Pool + /// + /// The page of partner network data, default is 0. + /// Amount of partner network data, default is 10. + /// The bpnls to get the selected record + /// Access token to access the partner network pool + /// + /// Returns a List of partner networks + Task GetPartnerNetworkDataAsync(int page, int size, PartnerNetworkRequest partnerNetworkRequest, string token, CancellationToken cancellationToken); } } diff --git a/src/administration/Administration.Service/BusinessLogic/PartnerNetworkBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/PartnerNetworkBusinessLogic.cs index 562083ed5f..331ed140ec 100644 --- a/src/administration/Administration.Service/BusinessLogic/PartnerNetworkBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/PartnerNetworkBusinessLogic.cs @@ -18,6 +18,9 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models; +using Org.Eclipse.TractusX.Portal.Backend.Bpdm.Library; +using Org.Eclipse.TractusX.Portal.Backend.Bpdm.Library.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; @@ -26,17 +29,155 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLog public class PartnerNetworkBusinessLogic : IPartnerNetworkBusinessLogic { private readonly IPortalRepositories _portalRepositories; + private readonly IBpnAccess _bpnAccess; /// /// Constructor /// /// - public PartnerNetworkBusinessLogic(IPortalRepositories portalRepositories) + /// + public PartnerNetworkBusinessLogic(IPortalRepositories portalRepositories, IBpnAccess bpnAccess) { _portalRepositories = portalRepositories; + _bpnAccess = bpnAccess; } /// public IAsyncEnumerable GetAllMemberCompaniesBPNAsync(IEnumerable? bpnIds) => _portalRepositories.GetInstance().GetAllMemberCompaniesBPNAsync(bpnIds?.Select(x => x.ToUpper())); + + /// + public async Task GetPartnerNetworkDataAsync(int page, int size, PartnerNetworkRequest partnerNetworkRequest, string token, CancellationToken cancellationToken) + { + var data = await _bpnAccess.FetchPartnerNetworkData(page, size, partnerNetworkRequest.Bpnls, partnerNetworkRequest.LegalName, token, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); + return new PartnerNetworkResponse(ParsePartnerNetworkData(data.Content), data.ContentSize, data.Page, data.TotalElements, data.TotalPages); + } + + private static IEnumerable ParsePartnerNetworkData(IEnumerable bpdmLegalEntityDtos) => + bpdmLegalEntityDtos.Select(data => + new PartnerNetworkData( + data.Bpn, + data.LegalName, + data.LegalShortName, + data.Currentness, + data.CreatedAt, + data.UpdatedAt, + data.Identifiers.Select(identifier => + new BpdmIdentifierData( + identifier.Value, + new BpdmTechnicalKeyData(identifier.Type.TechnicalKey, identifier.Type.Name), + identifier.IssuingBody + )), + data.LegalForm != null ? new BpdmLegalFormData( + data.LegalForm.TechnicalKey, + data.LegalForm.Name, + data.LegalForm.Abbreviation + ) : null, + data.States.Select(state => + new BpdmStatusData( + state.ValidFrom, + state.ValidTo, + new BpdmTechnicalKeyData(state!.Type!.TechnicalKey, state!.Type!.Name) + )), + data.ConfidenceCriteria != null ? new BpdmConfidenceCriteriaData( + data.ConfidenceCriteria.SharedByOwner, + data.ConfidenceCriteria.CheckedByExternalDataSource, + data.ConfidenceCriteria.NumberOfSharingMembers, + data.ConfidenceCriteria.LastConfidenceCheckAt, + data.ConfidenceCriteria.NextConfidenceCheckAt, + data.ConfidenceCriteria.ConfidenceLevel + ) : null, + data.IsCatenaXMemberData, + data.Relations.Select(relation => + new BpdmRelationData( + new BpdmTechnicalKeyData(relation.Type.TechnicalKey, relation.Type.Name), + relation.StartBpnl, + relation.EndBpnl, + relation.ValidFrom, + relation.ValidTo + )), + data.LegalEntityAddress != null ? new BpdmLegalEntityAddressData( + data.LegalEntityAddress.Bpna, + data.LegalEntityAddress.Name, + data.LegalEntityAddress.BpnLegalEntity, + data.LegalEntityAddress.BpnSite, + data.LegalEntityAddress.CreatedAt, + data.LegalEntityAddress.UpdatedAt, + data.LegalEntityAddress.AddressType, + data.LegalEntityAddress.States.Select(state => + new BpdmLegalEntityAddressStateData( + state.Description, + state.ValidFrom, + state.ValidTo, + new BpdmTechnicalKeyData(state.Type.TechnicalKey, state.Type.Name) + )), + data.LegalEntityAddress.Identifiers.Select(identifier => + new BpdmLegalEntityAddressIdentifierData( + identifier.Value, + new BpdmTechnicalKeyData(identifier.Type.TechnicalKey, identifier.Type.Name) + )), + data.LegalEntityAddress.PhysicalPostalAddress != null ? new BpdmPhysicalPostalAddressData( + data.LegalEntityAddress.PhysicalPostalAddress.GeographicCoordinates != null ? new BpdmGeographicCoordinatesData( + data.LegalEntityAddress.PhysicalPostalAddress.GeographicCoordinates.Longitude, + data.LegalEntityAddress.PhysicalPostalAddress.GeographicCoordinates.Latitude, + data.LegalEntityAddress.PhysicalPostalAddress.GeographicCoordinates.Altitude + ) : null, + data.LegalEntityAddress.PhysicalPostalAddress.Country != null ? new BpdmCountryData( + data.LegalEntityAddress.PhysicalPostalAddress.Country.TechnicalKey, + data.LegalEntityAddress.PhysicalPostalAddress.Country.Name + ) : null, + data.LegalEntityAddress.PhysicalPostalAddress.PostalCode, + data.LegalEntityAddress.PhysicalPostalAddress.City, + data.LegalEntityAddress.PhysicalPostalAddress.Street != null ? new BpdmStreetData( + data.LegalEntityAddress.PhysicalPostalAddress.Street.Name, + data.LegalEntityAddress.PhysicalPostalAddress.Street.HouseNumber, + data.LegalEntityAddress.PhysicalPostalAddress.Street.Milestone, + data.LegalEntityAddress.PhysicalPostalAddress.Street.Direction + ) : null, + data.LegalEntityAddress.PhysicalPostalAddress.AdministrativeAreaLevel1 != null ? new BpdmAdministrativeAreaLevelData( + data.LegalEntityAddress.PhysicalPostalAddress.AdministrativeAreaLevel1.CountryCode, + data.LegalEntityAddress.PhysicalPostalAddress.AdministrativeAreaLevel1.RegionName, + data.LegalEntityAddress.PhysicalPostalAddress.AdministrativeAreaLevel1.RegionCode + ) : null, + data.LegalEntityAddress.PhysicalPostalAddress.AdministrativeAreaLevel2, + data.LegalEntityAddress.PhysicalPostalAddress.AdministrativeAreaLevel3, + data.LegalEntityAddress.PhysicalPostalAddress.District, + data.LegalEntityAddress.PhysicalPostalAddress.CompanyPostalCode, + data.LegalEntityAddress.PhysicalPostalAddress.IndustrialZone, + data.LegalEntityAddress.PhysicalPostalAddress.Building, + data.LegalEntityAddress.PhysicalPostalAddress.Floor, + data.LegalEntityAddress.PhysicalPostalAddress.Door + ) : null, + data.LegalEntityAddress.AlternativePostalAddress != null ? new BpdmAlternativePostalAddressData( + data.LegalEntityAddress.AlternativePostalAddress.GeographicCoordinates != null ? new BpdmGeographicCoordinatesData( + data.LegalEntityAddress.AlternativePostalAddress.GeographicCoordinates.Longitude, + data.LegalEntityAddress.AlternativePostalAddress.GeographicCoordinates.Latitude, + data.LegalEntityAddress.AlternativePostalAddress.GeographicCoordinates.Altitude + ) : null, + data.LegalEntityAddress.AlternativePostalAddress.Country != null ? new BpdmCountryData( + data.LegalEntityAddress.AlternativePostalAddress.Country.TechnicalKey, + data.LegalEntityAddress.AlternativePostalAddress.Country.Name + ) : null, + data.LegalEntityAddress.AlternativePostalAddress.PostalCode, + data.LegalEntityAddress.AlternativePostalAddress.City, + data.LegalEntityAddress.AlternativePostalAddress.AdministrativeAreaLevel1 != null ? new BpdmAdministrativeAreaLevelData( + data.LegalEntityAddress.AlternativePostalAddress.AdministrativeAreaLevel1.CountryCode, + data.LegalEntityAddress.AlternativePostalAddress.AdministrativeAreaLevel1.RegionName, + data.LegalEntityAddress.AlternativePostalAddress.AdministrativeAreaLevel1.RegionCode + ) : null, + data.LegalEntityAddress.AlternativePostalAddress.DeliveryServiceNumber, + data.LegalEntityAddress.AlternativePostalAddress.DeliveryServiceType, + data.LegalEntityAddress.AlternativePostalAddress.DeliveryServiceQualifier + ) : null, + data.LegalEntityAddress.ConfidenceCriteria != null ? new BpdmConfidenceCriteriaData( + data.LegalEntityAddress.ConfidenceCriteria.SharedByOwner, + data.LegalEntityAddress.ConfidenceCriteria.CheckedByExternalDataSource, + data.LegalEntityAddress.ConfidenceCriteria.NumberOfSharingMembers, + data.LegalEntityAddress.ConfidenceCriteria.LastConfidenceCheckAt, + data.LegalEntityAddress.ConfidenceCriteria.NextConfidenceCheckAt, + data.LegalEntityAddress.ConfidenceCriteria.ConfidenceLevel + ) : null, + data.LegalEntityAddress.IsCatenaXMemberData + ) : null + )); } diff --git a/src/administration/Administration.Service/Controllers/PartnerNetworkController.cs b/src/administration/Administration.Service/Controllers/PartnerNetworkController.cs index e68c8c9d35..22917550fd 100644 --- a/src/administration/Administration.Service/Controllers/PartnerNetworkController.cs +++ b/src/administration/Administration.Service/Controllers/PartnerNetworkController.cs @@ -21,7 +21,10 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLogic; +using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models; +using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Web; using Org.Eclipse.TractusX.Portal.Backend.Framework.Web; +using Org.Eclipse.TractusX.Portal.Backend.Keycloak.Authentication; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; using Org.Eclipse.TractusX.Portal.Backend.Web.PublicInfos; @@ -60,4 +63,23 @@ public PartnerNetworkController(IPartnerNetworkBusinessLogic logic) [PublicUrl(CompanyRoleId.ACTIVE_PARTICIPANT, CompanyRoleId.SERVICE_PROVIDER, CompanyRoleId.APP_PROVIDER)] public IAsyncEnumerable GetAllMemberCompaniesBPNAsync([FromQuery] IEnumerable? bpnIds = null) => _logic.GetAllMemberCompaniesBPNAsync(bpnIds); + + /// + /// Gets partner network data from BPN Pool + /// + /// The page of partner network data, default is 0. + /// Amount of partner network data, default is 10. + /// The bpnls to get the selected record + /// + /// Returns a List of partner networks + /// Example: Get: /api/registration/legalEntities/search?page=0&size=10&bpnl= + /// Returns the list of partner networks + /// The requested service responded with the given error. + [HttpPost] + [Authorize(Roles = "view_partner_network")] + [Route("legalEntities/search")] + [ProducesResponseType(typeof(PartnerNetworkResponse), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status503ServiceUnavailable)] + public Task GetPartnerNetworkDataAsync([FromBody] PartnerNetworkRequest partnerNetworkRequest, [FromQuery] int page = 0, [FromQuery] int size = 10, CancellationToken cancellationToken = default) => + this.WithBearerToken(token => _logic.GetPartnerNetworkDataAsync(page, size, partnerNetworkRequest, token, cancellationToken)); } diff --git a/src/administration/Administration.Service/Models/PartnerNetworkRequest.cs b/src/administration/Administration.Service/Models/PartnerNetworkRequest.cs new file mode 100644 index 0000000000..01a4d31e1a --- /dev/null +++ b/src/administration/Administration.Service/Models/PartnerNetworkRequest.cs @@ -0,0 +1,26 @@ +/******************************************************************************** + * Copyright (c) 2022 BMW Group AG + * Copyright (c) 2022 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models; + +public record PartnerNetworkRequest( + IEnumerable Bpnls, + string LegalName +); diff --git a/src/administration/Administration.Service/Models/PartnerNetworkResponse.cs b/src/administration/Administration.Service/Models/PartnerNetworkResponse.cs new file mode 100644 index 0000000000..30905c3d4c --- /dev/null +++ b/src/administration/Administration.Service/Models/PartnerNetworkResponse.cs @@ -0,0 +1,169 @@ +/******************************************************************************** + * Copyright (c) 2022 BMW Group AG + * Copyright (c) 2022 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models; + +public record PartnerNetworkResponse( + IEnumerable Content, + int ContentSize, + int Page, + int TotalElements, + int TotalPages +); + +public record PartnerNetworkData( + string Bpn, + string? LegalName, + string? LegalShortName, + DateTimeOffset Currentness, + DateTimeOffset CreatedAt, + DateTimeOffset UpdatedAt, + IEnumerable Identifiers, + BpdmLegalFormData? LegalForm, + IEnumerable States, + BpdmConfidenceCriteriaData? ConfidenceCriteria, + bool IsCatenaXMemberData, + IEnumerable Relations, + BpdmLegalEntityAddressData? LegalEntityAddress +); + +public record BpdmIdentifierData( + string Value, + BpdmTechnicalKeyData Type, + string? IssuingBody +); + +public record BpdmTechnicalKeyData( + string TechnicalKey, + string Name +); + +public record BpdmLegalFormData( + string? TechnicalKey, + string? Name, + string? Abbreviation +); + +public record BpdmStatusData( + DateTimeOffset? ValidFrom, + DateTimeOffset? ValidTo, + BpdmTechnicalKeyData Type +); + +public record BpdmConfidenceCriteriaData( + bool SharedByOwner, + bool CheckedByExternalDataSource, + int NumberOfSharingMembers, + DateTime LastConfidenceCheckAt, + DateTime NextConfidenceCheckAt, + int ConfidenceLevel +); + +public record BpdmRelationData( + BpdmTechnicalKeyData Type, + string? StartBpnl, + string? EndBpnl, + DateTimeOffset? ValidFrom, + DateTimeOffset? ValidTo +); + +public record BpdmLegalEntityAddressData +( + string? Bpna, + string? Name, + string? BpnLegalEntity, + string? BpnSite, + DateTimeOffset CreatedAt, + DateTimeOffset UpdatedAt, + string AddressType, + IEnumerable States, + IEnumerable Identifiers, + BpdmPhysicalPostalAddressData? PhysicalPostalAddress, + BpdmAlternativePostalAddressData? AlternativePostalAddress, + BpdmConfidenceCriteriaData? ConfidenceCriteria, + bool IsCatenaXMemberData +); + +public record BpdmLegalEntityAddressStateData +( + string? Description, + DateTimeOffset? ValidFrom, + DateTimeOffset? ValidTo, + BpdmTechnicalKeyData Type +); + +public record BpdmLegalEntityAddressIdentifierData +( + string? Value, + BpdmTechnicalKeyData Type +); + +public record BpdmPhysicalPostalAddressData( + BpdmGeographicCoordinatesData? GeographicCoordinates, + BpdmCountryData? Country, + string? PostalCode, + string? City, + BpdmStreetData? Street, + BpdmAdministrativeAreaLevelData? AdministrativeAreaLevel1, + string? AdministrativeAreaLevel2, + string? AdministrativeAreaLevel3, + string? District, + string? CompanyPostalCode, + string? IndustrialZone, + string? Building, + string? Floor, + string? Door +); + +public record BpdmAlternativePostalAddressData( + BpdmGeographicCoordinatesData? GeographicCoordinates, + BpdmCountryData? Country, + string? PostalCode, + string? City, + BpdmAdministrativeAreaLevelData? AdministrativeAreaLevel1, + string? DeliveryServiceNumber, + string? DeliveryServiceType, + string? DeliveryServiceQualifier +); + +public record BpdmGeographicCoordinatesData( + double Longitude, + double Latitude, + double? Altitude +); + +public record BpdmCountryData +( + string TechnicalKey, + string Name +); + +public record BpdmStreetData( + string? Name, + string? HouseNumber, + string? Milestone, + string? Direction +); + +public record BpdmAdministrativeAreaLevelData( + string? CountryCode, + string? RegionName, + string? RegionCode +); diff --git a/src/administration/Administration.Service/Program.cs b/src/administration/Administration.Service/Program.cs index 33b94cc7d4..c6ff2b4058 100644 --- a/src/administration/Administration.Service/Program.cs +++ b/src/administration/Administration.Service/Program.cs @@ -21,6 +21,7 @@ using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.DependencyInjection; using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.ErrorHandling; using Org.Eclipse.TractusX.Portal.Backend.Bpdm.Library.DependencyInjection; +using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling.Service; using Org.Eclipse.TractusX.Portal.Backend.Framework.Models; using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Extensions; @@ -80,6 +81,8 @@ await WebAppHelper builder.Services.AddApplicationChecklist(builder.Configuration.GetSection("ApplicationChecklist")) .AddOfferSubscriptionProcess(); + builder.Services.AddBpnAccess(builder.Configuration.GetValue("BPN_Address") ?? throw new ConfigurationException("BPN_Address is not configured")); + builder.Services.AddTransient() .ConfigureConnectorsSettings(builder.Configuration.GetSection("Connectors")); diff --git a/src/administration/Administration.Service/appsettings.json b/src/administration/Administration.Service/appsettings.json index 55fa24eb0d..f60d1a8d0f 100644 --- a/src/administration/Administration.Service/appsettings.json +++ b/src/administration/Administration.Service/appsettings.json @@ -26,6 +26,7 @@ "Cors": { "AllowedOrigins": [] }, + "BPN_Address": "", "Keycloak": { "central": { "ConnectionString": "", diff --git a/src/externalsystems/Bpdm.Library/BpnAccess.cs b/src/externalsystems/Bpdm.Library/BpnAccess.cs index 3ccd20de41..60e9fee9fc 100644 --- a/src/externalsystems/Bpdm.Library/BpnAccess.cs +++ b/src/externalsystems/Bpdm.Library/BpnAccess.cs @@ -22,6 +22,7 @@ using Org.Eclipse.TractusX.Portal.Backend.Framework.HttpClientExtensions; using System.Net.Http.Headers; using System.Net.Http.Json; +using System.Text; using System.Text.Json; namespace Org.Eclipse.TractusX.Portal.Backend.Bpdm.Library; @@ -52,4 +53,36 @@ public async Task FetchLegalEntityByBpn(string businessPartn throw new ServiceException($"Access to external system bpdm did not return a valid json response: {je.Message}"); } } + + public async Task FetchPartnerNetworkData(int page, int size, IEnumerable bpnl, string legalName, string token, CancellationToken cancellationToken) + { + _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + var uri = new UriBuilder + { + Path = $"members/legal-entities/search", + Query = $"page={page}&size={size}" + }.Uri; + var request = new BpdmPartnerNetworkRequest(bpnl, legalName); + var content = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json"); + + async ValueTask<(bool, string?)> CreateErrorMessage(HttpResponseMessage errorResponse) => + (false, (await errorResponse.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None))); + + var result = await _httpClient.PostAsync(uri.PathAndQuery.TrimStart('/'), content, cancellationToken) + .CatchingIntoServiceExceptionFor("fetch-partner-network", HttpAsyncResponseMessageExtension.RecoverOptions.INFRASTRUCTURE, CreateErrorMessage) + .ConfigureAwait(false); + try + { + var response = await result.Content.ReadFromJsonAsync(Options, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); + if (response == null || response.Content == null) + { + throw new ServiceException("Access to external system bpdm did not return a valid legal entity response"); + } + return response; + } + catch (JsonException je) + { + throw new ServiceException($"Access to external system bpdm did not return a valid json response: {je.Message}"); + } + } } diff --git a/src/externalsystems/Bpdm.Library/IBpnAccess.cs b/src/externalsystems/Bpdm.Library/IBpnAccess.cs index 8038ba574f..6047d94a88 100644 --- a/src/externalsystems/Bpdm.Library/IBpnAccess.cs +++ b/src/externalsystems/Bpdm.Library/IBpnAccess.cs @@ -25,4 +25,6 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Bpdm.Library; public interface IBpnAccess { Task FetchLegalEntityByBpn(string businessPartnerNumber, string token, CancellationToken cancellationToken); + + Task FetchPartnerNetworkData(int page, int size, IEnumerable bpnl, string legalName, string token, CancellationToken cancellationToken); } diff --git a/src/externalsystems/Bpdm.Library/Models/BpdmPartnerNetworkData.cs b/src/externalsystems/Bpdm.Library/Models/BpdmPartnerNetworkData.cs new file mode 100644 index 0000000000..e67f270af0 --- /dev/null +++ b/src/externalsystems/Bpdm.Library/Models/BpdmPartnerNetworkData.cs @@ -0,0 +1,31 @@ +/******************************************************************************** + * Copyright (c) 2022 Microsoft and BMW Group AG + * Copyright (c) 2022 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using System.Text.Json.Serialization; + +namespace Org.Eclipse.TractusX.Portal.Backend.Bpdm.Library.Models; + +public record BpdmPartnerNetworkData( + [property: JsonPropertyName("content")] IEnumerable Content, + [property: JsonPropertyName("contentSize")] int ContentSize, + [property: JsonPropertyName("page")] int Page, + [property: JsonPropertyName("totalElements")] int TotalElements, + [property: JsonPropertyName("totalPages")] int TotalPages +); diff --git a/src/externalsystems/Bpdm.Library/Models/BpdmPartnerNetworkRequest.cs b/src/externalsystems/Bpdm.Library/Models/BpdmPartnerNetworkRequest.cs new file mode 100644 index 0000000000..03cfb6bdf6 --- /dev/null +++ b/src/externalsystems/Bpdm.Library/Models/BpdmPartnerNetworkRequest.cs @@ -0,0 +1,28 @@ +/******************************************************************************** + * Copyright (c) 2022 Microsoft and BMW Group AG + * Copyright (c) 2022 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +using System.Text.Json.Serialization; + +namespace Org.Eclipse.TractusX.Portal.Backend.Bpdm.Library.Models; + +public record BpdmPartnerNetworkRequest( + [property: JsonPropertyName("bpnLs")] IEnumerable Bpnls, + [property: JsonPropertyName("legalName")] string LegalName +); diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/PartnerNetworkBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/PartnerNetworkBusinessLogicTests.cs index 8332690235..059bbb404a 100644 --- a/tests/administration/Administration.Service.Tests/BusinessLogic/PartnerNetworkBusinessLogicTests.cs +++ b/tests/administration/Administration.Service.Tests/BusinessLogic/PartnerNetworkBusinessLogicTests.cs @@ -17,6 +17,9 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models; +using Org.Eclipse.TractusX.Portal.Backend.Bpdm.Library; +using Org.Eclipse.TractusX.Portal.Backend.Bpdm.Library.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; @@ -25,6 +28,7 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLog public class PartnerNetworkBusinessLogicTests { private readonly IPortalRepositories _portalRepositories; + private readonly IBpnAccess _bpnAccess; private readonly ICompanyRepository _companyRepository; private readonly IPartnerNetworkBusinessLogic _sut; private readonly IFixture _fixture; @@ -37,11 +41,12 @@ public PartnerNetworkBusinessLogicTests() _fixture.Behaviors.Add(new OmitOnRecursionBehavior()); _portalRepositories = A.Fake(); + _bpnAccess = A.Fake(); _companyRepository = A.Fake(); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_companyRepository); - _sut = new PartnerNetworkBusinessLogic(_portalRepositories); + _sut = new PartnerNetworkBusinessLogic(_portalRepositories, _bpnAccess); } [Fact] @@ -60,4 +65,95 @@ public async Task GetAllMemberCompaniesBPNAsync_ReturnsExpected() result.Should().NotBeNull().And.HaveCount(2); A.CallTo(() => _companyRepository.GetAllMemberCompaniesBPNAsync(A>.That.IsSameSequenceAs(uppercaseIds))).MustHaveHappenedOnceExactly(); } + + #region GetPartnerNetworkDataAsync + + [Fact] + public async Task GetPartnerNetworkDataAsync_List_ReturnsExpected() + { + // Arrange + var token = _fixture.Create(); + var totalElements = 30; + var request = new PartnerNetworkRequest(_fixture.CreateMany(totalElements), ""); + var page = 0; + var size = 10; + var totalPages = totalElements / size; + var legalEntities = _fixture.CreateMany(size); + + var responseDto = _fixture.Build() + .With(x => x.Content, legalEntities) + .With(x => x.ContentSize, size) + .With(x => x.TotalElements, totalElements) + .With(x => x.TotalPages, totalPages) + .With(x => x.Page, page) + .Create(); + + A.CallTo(() => _bpnAccess.FetchPartnerNetworkData(page, size, request.Bpnls, request.LegalName, token, A._)) + .Returns(responseDto); + + // Act + var result = await _sut + .GetPartnerNetworkDataAsync(page, size, request, token, CancellationToken.None); + + A.CallTo(() => _bpnAccess.FetchPartnerNetworkData(page, size, request.Bpnls, request.LegalName, token, A._)) + .MustHaveHappenedOnceExactly(); + + result.Should().NotBeNull(); + result.Content.Should().HaveCount(size); + result.TotalElements.Should().Be(totalElements); + result.Page.Should().Be(page); + result.TotalPages.Should().Be(totalPages); + } + + [Fact] + public async Task GetPartnerNetworkDataAsync_Selected_ReturnsExpected() + { + // Arrange + var token = _fixture.Create(); + var totalElements = 1; + var businessPartnerNumber = "THISBPNISVALID12"; + var bpnls = new string[] { businessPartnerNumber }.AsEnumerable(); + var request = new PartnerNetworkRequest(bpnls, ""); + var page = 0; + var size = 1; + var totalPages = totalElements / size; + + var bpdmAddress = _fixture.Build() + .With(x => x.Bpna, businessPartnerNumber) + .Create(); + + var legalEntity = _fixture.Build() + .With(x => x.Bpn, businessPartnerNumber) + .With(x => x.LegalEntityAddress, bpdmAddress) + .Create(); + + var legalEntities = new BpdmLegalEntityDto[] { legalEntity }.AsEnumerable(); + + var responseDto = _fixture.Build() + .With(x => x.Content, legalEntities) + .With(x => x.ContentSize, size) + .With(x => x.TotalElements, totalElements) + .With(x => x.TotalPages, totalPages) + .With(x => x.Page, page) + .Create(); + + A.CallTo(() => _bpnAccess.FetchPartnerNetworkData(page, size, request.Bpnls, request.LegalName, token, A._)) + .Returns(responseDto); + + // Act + var result = await _sut + .GetPartnerNetworkDataAsync(page, size, request, token, CancellationToken.None); + + A.CallTo(() => _bpnAccess.FetchPartnerNetworkData(page, size, request.Bpnls, request.LegalName, token, A._)) + .MustHaveHappenedOnceExactly(); + + result.Should().NotBeNull(); + result.Content.First().Bpn.Should().Be(businessPartnerNumber); + result.Content.Should().HaveCount(size); + result.TotalElements.Should().Be(totalElements); + result.Page.Should().Be(page); + result.TotalPages.Should().Be(totalPages); + } + + #endregion } diff --git a/tests/administration/Administration.Service.Tests/Controllers/PartnerNetworkControllerTest.cs b/tests/administration/Administration.Service.Tests/Controllers/PartnerNetworkControllerTest.cs index ba322e4738..b8b83d2770 100644 --- a/tests/administration/Administration.Service.Tests/Controllers/PartnerNetworkControllerTest.cs +++ b/tests/administration/Administration.Service.Tests/Controllers/PartnerNetworkControllerTest.cs @@ -19,6 +19,9 @@ using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLogic; using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Controllers; +using Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities; +using Org.Eclipse.TractusX.Portal.Backend.Tests.Shared.Extensions; namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Tests.Controllers; @@ -37,6 +40,9 @@ public PartnerNetworkControllerTest() _fixture.Behaviors.Add(new OmitOnRecursionBehavior()); _logic = A.Fake(); _controller = new PartnerNetworkController(_logic); + var identity = A.Fake(); + A.CallTo(() => identity.IdentityId).Returns(Guid.NewGuid()); + _controller.AddControllerContextWithClaimAndBearer("ac-token", identity); } [Theory] @@ -59,4 +65,19 @@ public async Task GetAllMemberCompaniesBPN_Test(params string[]? bpnIds) result.Should().HaveSameCount(data).And.ContainInOrder(data); } + + [Fact] + public async Task GetPartnerNetworkDataAsync_ReturnsExpected() + { + //Arrange + var request = new PartnerNetworkRequest(_fixture.CreateMany(3), ""); + var page = 0; + var size = 1; + + // Act + await _controller.GetPartnerNetworkDataAsync(request, page, size, CancellationToken.None); + + // Assert + A.CallTo(() => _logic.GetPartnerNetworkDataAsync(page, size, request, "ac-token", A._)).MustHaveHappenedOnceExactly(); + } } diff --git a/tests/externalsystems/Bpdm.Library/BPNAccessTest.cs b/tests/externalsystems/Bpdm.Library/BPNAccessTest.cs index 01bc7bb65a..6f2e337bed 100644 --- a/tests/externalsystems/Bpdm.Library/BPNAccessTest.cs +++ b/tests/externalsystems/Bpdm.Library/BPNAccessTest.cs @@ -309,4 +309,327 @@ public async Task FetchLegalEntityByBpn_UnsuccessfulCall_Throws() } #endregion + + #region FetchPartnerNetworkData + + [Fact] + public async Task FetchPartnerNetworkData_Success_ReturnsExpected() + { + //Arrange + HttpRequestMessage? request = null; + + const string json = @"{ + ""totalElements"": 46, + ""totalPages"": 5, + ""page"": 0, + ""contentSize"": 10, + ""content"": [ + { + ""bpnl"": ""BPNL000000000001"", + ""legalName"": ""Comapany Test Auto"", + ""legalShortName"": ""CTA"", + ""legalForm"": { + ""technicalKey"": ""CUSTOM_LEGAL_FORM_f254bb28-92f2-4b49-81a8-f364cde5a5cc"", + ""name"": ""Legal Form for Test Automation"", + ""abbreviation"": null + }, + ""identifiers"": [ + { + ""value"": ""1c4815e7-c5b6-41a3-862a-a815ee2a836e"", + ""type"": { + ""technicalKey"": ""CUSTOM_LE_ID_e6e534ac-ff59-40ab-bd0d-da94f73f700e"", + ""name"": ""Custom Identifier Type of LE for Test Automation"" + }, + ""issuingBody"": ""ISSUE_BODY_TEST_AUTO"" + } + ], + ""states"": [ + { + ""validFrom"": ""2023-07-16T05:54:48.942"", + ""validTo"": ""2024-06-09T07:31:01.213"", + ""type"": { + ""technicalKey"": ""ACTIVE"", + ""name"": ""Active"" + } + } + ], + ""relations"": [ + + ], + ""currentness"": ""2023-09-20T05:31:17.009357Z"", + ""confidenceCriteria"": { + ""sharedByOwner"": false, + ""checkedByExternalDataSource"": false, + ""numberOfSharingMembers"": 1, + ""lastConfidenceCheckAt"": ""2023-12-29T07:56:51.44798"", + ""nextConfidenceCheckAt"": ""2023-12-29T07:56:51.44798"", + ""confidenceLevel"": 0 + }, + ""isCatenaXMemberData"": true, + ""createdAt"": ""2023-09-20T05:31:17.090516Z"", + ""updatedAt"": ""2023-09-20T05:31:17.090523Z"", + ""legalAddress"": { + ""bpna"": ""BPNA000000000001"", + ""name"": ""ADDRESS_TEST_AUTO"", + ""states"": [ + { + ""validFrom"": ""2023-07-16T05:54:48.942"", + ""validTo"": ""2024-06-05T07:31:01.213"", + ""type"": { + ""technicalKey"": ""ACTIVE"", + ""name"": ""Active"" + } + } + ], + ""identifiers"": [ + { + ""value"": ""1c4815e7-c5b6-41a3-862a-a815ee2a836e"", + ""type"": { + ""technicalKey"": ""CUSTOM_ADD_ID_0501e165-a446-40f9-b49b-63158abec717"", + ""name"": ""Custom Identifier Type of Test Automation"" + } + } + ], + ""physicalPostalAddress"": { + ""geographicCoordinates"": { + ""longitude"": 0.0, + ""latitude"": 0.0, + ""altitude"": 0.0 + }, + ""country"": { + ""technicalKey"": ""DE"", + ""name"": ""Germany"" + }, + ""administrativeAreaLevel1"": null, + ""administrativeAreaLevel2"": ""test1"", + ""administrativeAreaLevel3"": ""test2"", + ""postalCode"": ""1111"", + ""city"": ""TestCity"", + ""district"": ""Test district"", + ""street"": { + ""name"": ""Stuttgarter Strasse"", + ""houseNumber"": ""1"", + ""houseNumberSupplement"": null, + ""milestone"": ""Test milestone 1"", + ""direction"": ""Test direction 1"", + ""namePrefix"": null, + ""additionalNamePrefix"": null, + ""nameSuffix"": null, + ""additionalNameSuffix"": null + }, + ""companyPostalCode"": ""1234"", + ""industrialZone"": ""Test industrialZone 1"", + ""building"": ""Test building 1"", + ""floor"": ""F"", + ""door"": ""test door 1"" + }, + ""alternativePostalAddress"": { + ""geographicCoordinates"": { + ""longitude"": 0.0, + ""latitude"": 0.0, + ""altitude"": null + }, + ""country"": { + ""technicalKey"": ""DE"", + ""name"": ""Germany"" + }, + ""administrativeAreaLevel1"": null, + ""postalCode"": ""2222"", + ""city"": ""Test city 2"", + ""deliveryServiceType"": ""PO_BOX"", + ""deliveryServiceQualifier"": ""test deliveryServiceQualifier"", + ""deliveryServiceNumber"": ""2222"" + }, + ""bpnLegalEntity"": ""BPNL000000000001"", + ""bpnSite"": null, + ""isCatenaXMemberData"": true, + ""createdAt"": ""2023-09-20T05:31:17.084880Z"", + ""updatedAt"": ""2023-09-20T05:31:17.096188Z"", + ""confidenceCriteria"": { + ""sharedByOwner"": false, + ""checkedByExternalDataSource"": false, + ""numberOfSharingMembers"": 1, + ""lastConfidenceCheckAt"": ""2023-12-29T07:56:51.44798"", + ""nextConfidenceCheckAt"": ""2023-12-29T07:56:51.44798"", + ""confidenceLevel"": 0 + }, + ""addressType"": ""LegalAddress"" + } + } + ] + }"; + + using var responseMessage = new HttpResponseMessage + { + StatusCode = HttpStatusCode.OK, + Content = new StringContent(json) + }; + _fixture.ConfigureHttpClientFactoryFixture("pnd", responseMessage, requestMessage => request = requestMessage); + + var token = _fixture.Create(); + var totalElements = 30; + var bpnls = _fixture.CreateMany(totalElements); + var legalName = _fixture.Create(); + var page = 0; + var size = 10; + var sut = _fixture.Create(); + + //Act + var result = await sut.FetchPartnerNetworkData(page, size, bpnls, legalName, token, CancellationToken.None); + + //Assert + request.Should().NotBeNull(); + request!.RequestUri.Should().NotBeNull(); + request.RequestUri.Should().NotBeNull(); + request.RequestUri!.LocalPath.Should().Be($"/members/legal-entities/search"); + request.RequestUri.Query.Should().Be($"?page={page}&size={size}"); + + result.Should().NotBeNull(); + result.Content.Should().NotBeNull(); + result.Content.First().LegalEntityAddress!.Bpna.Should().Be("BPNA000000000001"); + } + + [Fact] + public async Task FetchPartnerNetworkData_InvalidJsonResponse_Throws() + { + //Arrange + var json = _fixture.Create(); + using var responseMessage = new HttpResponseMessage + { + StatusCode = HttpStatusCode.OK, + Content = new StringContent(json) + }; + _fixture.ConfigureHttpClientFactoryFixture("pnd", responseMessage); + + var token = _fixture.Create(); + var totalElements = 30; + var bpnls = _fixture.CreateMany(totalElements); + var legalName = _fixture.Create(); + var page = 0; + var size = 10; + var sut = _fixture.Create(); + + //Act + var Act = () => sut.FetchPartnerNetworkData(page, size, bpnls, legalName, token, CancellationToken.None); + var result = await Assert.ThrowsAsync(Act); + + //Assert + result.Should().NotBeNull(); + result.Message.Should().StartWith("Access to external system bpdm did not return a valid json response"); + } + + [Fact] + public async Task FetchPartnerNetworkData_EmptyResponse_Throws() + { + //Arrange + const string json = ""; + using var responseMessage = new HttpResponseMessage + { + StatusCode = HttpStatusCode.OK, + Content = new StringContent(json) + }; + _fixture.ConfigureHttpClientFactoryFixture("pnd", responseMessage); + + var token = _fixture.Create(); + var totalElements = 30; + var bpnls = _fixture.CreateMany(totalElements); + var legalName = _fixture.Create(); + var page = 0; + var size = 10; + var sut = _fixture.Create(); + + //Act + var Act = () => sut.FetchPartnerNetworkData(page, size, bpnls, legalName, token, CancellationToken.None); + var result = await Assert.ThrowsAsync(Act); + + //Assert + result.Should().NotBeNull(); + result.Message.Should().StartWith("Access to external system bpdm did not return a valid json response"); + } + + [Fact] + public async Task FetchPartnerNetworkData_NoContentResponse_Throws() + { + //Arrange + using var responseMessage = new HttpResponseMessage + { + StatusCode = HttpStatusCode.OK, + }; + _fixture.ConfigureHttpClientFactoryFixture("pnd", responseMessage); + + var token = _fixture.Create(); + var totalElements = 30; + var bpnls = _fixture.CreateMany(totalElements); + var legalName = _fixture.Create(); + var page = 0; + var size = 10; + var sut = _fixture.Create(); + + //Act + var Act = () => sut.FetchPartnerNetworkData(page, size, bpnls, legalName, token, CancellationToken.None); + var result = await Assert.ThrowsAsync(Act); + + //Assert + result.Should().NotBeNull(); + result.Message.Should().StartWith("Access to external system bpdm did not return a valid json response"); + } + + [Fact] + public async Task FetchPartnerNetworkData_InvalidJsonType_Throws() + { + //Arrange + const string json = "{\"some\": [{\"other\": \"json\"}]}"; + using var responseMessage = new HttpResponseMessage + { + StatusCode = HttpStatusCode.OK, + Content = new StringContent(json) + }; + _fixture.ConfigureHttpClientFactoryFixture("pnd", responseMessage); + + var token = _fixture.Create(); + var totalElements = 30; + var bpnls = _fixture.CreateMany(totalElements); + var legalName = _fixture.Create(); + var page = 0; + var size = 10; + var sut = _fixture.Create(); + + //Act + var Act = () => sut.FetchPartnerNetworkData(page, size, bpnls, legalName, token, CancellationToken.None); + var result = await Assert.ThrowsAsync(Act); + + //Assert + result.Should().NotBeNull(); + result.Message.Should().StartWith("Access to external system bpdm did not return a valid legal entity response"); + } + + [Fact] + public async Task FetchPartnerNetworkData_UnsuccessfulCall_Throws() + { + //Arrange + var json = _fixture.Create(); + using var responseMessage = new HttpResponseMessage + { + StatusCode = HttpStatusCode.BadRequest, + Content = new StringContent(json) + }; + _fixture.ConfigureHttpClientFactoryFixture("pnd", responseMessage); + + var token = _fixture.Create(); + var totalElements = 30; + var bpnls = _fixture.CreateMany(totalElements); + var legalName = _fixture.Create(); + var page = 0; + var size = 10; + var sut = _fixture.Create(); + + //Act + var Act = () => sut.FetchPartnerNetworkData(page, size, bpnls, legalName, token, CancellationToken.None); + var result = await Assert.ThrowsAsync(Act); + + //Assert + result.Message.Should().Contain($"call to external system fetch-partner-network failed with statuscode {(int)HttpStatusCode.BadRequest}"); + } + + #endregion } From aa10e9305461b96d82481773cbd475cb31b14e1d Mon Sep 17 00:00:00 2001 From: Tayyab Fayyaz Janjua Date: Mon, 21 Oct 2024 14:43:44 +0200 Subject: [PATCH 2/3] removed BPN_Address config becasue now we have BpnAccess section in appsettings file. --- docs/api/administration-service.yaml | 387 ++++++++++++++++++ .../Administration.Service/Program.cs | 2 - .../Administration.Service/appsettings.json | 1 - src/externalsystems/Bpdm.Library/BpnAccess.cs | 5 +- 4 files changed, 390 insertions(+), 5 deletions(-) diff --git a/docs/api/administration-service.yaml b/docs/api/administration-service.yaml index 767f683201..c74fda790c 100644 --- a/docs/api/administration-service.yaml +++ b/docs/api/administration-service.yaml @@ -3182,6 +3182,52 @@ paths: description: Internal Server Error '401': description: The User is unauthorized + /api/administration/PartnerNetwork/legalEntities/search: + post: + tags: + - PartnerNetwork + summary: 'Gets partner network data from BPN Pool (Authorization required - Roles: view_partner_network)' + description: 'Example: Get: /api/registration/legalEntities/search?page=0&size=10&bpnl=' + parameters: + - name: page + in: query + description: 'The page of partner network data, default is 0.' + schema: + type: integer + format: int32 + default: 0 + example: 0 + - name: size + in: query + description: 'Amount of partner network data, default is 10.' + schema: + type: integer + format: int32 + default: 10 + example: 10 + requestBody: + description: The bpnls to get the selected record + content: + application/json: + schema: + $ref: '#/components/schemas/PartnerNetworkRequest' + responses: + '200': + description: Returns the list of partner networks + content: + application/json: + schema: + $ref: '#/components/schemas/PartnerNetworkResponse' + '503': + description: The requested service responded with the given error. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '500': + description: Internal Server Error + '401': + description: The User is unauthorized '/api/administration/registration/application/{applicationId}/companyDetailsWithAddress': get: tags: @@ -5997,6 +6043,276 @@ components: clientSecret: type: string additionalProperties: false + BpdmAdministrativeAreaLevelData: + type: object + properties: + countryCode: + type: string + nullable: true + regionName: + type: string + nullable: true + regionCode: + type: string + nullable: true + additionalProperties: false + BpdmAlternativePostalAddressData: + type: object + properties: + geographicCoordinates: + $ref: '#/components/schemas/BpdmGeographicCoordinatesData' + country: + $ref: '#/components/schemas/BpdmCountryData' + postalCode: + type: string + nullable: true + city: + type: string + nullable: true + administrativeAreaLevel1: + $ref: '#/components/schemas/BpdmAdministrativeAreaLevelData' + deliveryServiceNumber: + type: string + nullable: true + deliveryServiceType: + type: string + nullable: true + deliveryServiceQualifier: + type: string + nullable: true + additionalProperties: false + BpdmConfidenceCriteriaData: + type: object + properties: + sharedByOwner: + type: boolean + checkedByExternalDataSource: + type: boolean + numberOfSharingMembers: + type: integer + format: int32 + lastConfidenceCheckAt: + type: string + format: date-time + nextConfidenceCheckAt: + type: string + format: date-time + confidenceLevel: + type: integer + format: int32 + additionalProperties: false + BpdmCountryData: + type: object + properties: + technicalKey: + type: string + name: + type: string + additionalProperties: false + BpdmGeographicCoordinatesData: + type: object + properties: + longitude: + type: number + format: double + latitude: + type: number + format: double + altitude: + type: number + format: double + nullable: true + additionalProperties: false + BpdmIdentifierData: + type: object + properties: + value: + type: string + type: + $ref: '#/components/schemas/BpdmTechnicalKeyData' + issuingBody: + type: string + nullable: true + additionalProperties: false + BpdmLegalEntityAddressData: + type: object + properties: + bpna: + type: string + nullable: true + name: + type: string + nullable: true + bpnLegalEntity: + type: string + nullable: true + bpnSite: + type: string + nullable: true + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + addressType: + type: string + states: + type: array + items: + $ref: '#/components/schemas/BpdmLegalEntityAddressStateData' + identifiers: + type: array + items: + $ref: '#/components/schemas/BpdmLegalEntityAddressIdentifierData' + physicalPostalAddress: + $ref: '#/components/schemas/BpdmPhysicalPostalAddressData' + alternativePostalAddress: + $ref: '#/components/schemas/BpdmAlternativePostalAddressData' + confidenceCriteria: + $ref: '#/components/schemas/BpdmConfidenceCriteriaData' + isCatenaXMemberData: + type: boolean + additionalProperties: false + BpdmLegalEntityAddressIdentifierData: + type: object + properties: + value: + type: string + nullable: true + type: + $ref: '#/components/schemas/BpdmTechnicalKeyData' + additionalProperties: false + BpdmLegalEntityAddressStateData: + type: object + properties: + description: + type: string + nullable: true + validFrom: + type: string + format: date-time + nullable: true + validTo: + type: string + format: date-time + nullable: true + type: + $ref: '#/components/schemas/BpdmTechnicalKeyData' + additionalProperties: false + BpdmLegalFormData: + type: object + properties: + technicalKey: + type: string + nullable: true + name: + type: string + nullable: true + abbreviation: + type: string + nullable: true + additionalProperties: false + BpdmPhysicalPostalAddressData: + type: object + properties: + geographicCoordinates: + $ref: '#/components/schemas/BpdmGeographicCoordinatesData' + country: + $ref: '#/components/schemas/BpdmCountryData' + postalCode: + type: string + nullable: true + city: + type: string + nullable: true + street: + $ref: '#/components/schemas/BpdmStreetData' + administrativeAreaLevel1: + $ref: '#/components/schemas/BpdmAdministrativeAreaLevelData' + administrativeAreaLevel2: + type: string + nullable: true + administrativeAreaLevel3: + type: string + nullable: true + district: + type: string + nullable: true + companyPostalCode: + type: string + nullable: true + industrialZone: + type: string + nullable: true + building: + type: string + nullable: true + floor: + type: string + nullable: true + door: + type: string + nullable: true + additionalProperties: false + BpdmRelationData: + type: object + properties: + type: + $ref: '#/components/schemas/BpdmTechnicalKeyData' + startBpnl: + type: string + nullable: true + endBpnl: + type: string + nullable: true + validFrom: + type: string + format: date-time + nullable: true + validTo: + type: string + format: date-time + nullable: true + additionalProperties: false + BpdmStatusData: + type: object + properties: + validFrom: + type: string + format: date-time + nullable: true + validTo: + type: string + format: date-time + nullable: true + type: + $ref: '#/components/schemas/BpdmTechnicalKeyData' + additionalProperties: false + BpdmStreetData: + type: object + properties: + name: + type: string + nullable: true + houseNumber: + type: string + nullable: true + milestone: + type: string + nullable: true + direction: + type: string + nullable: true + additionalProperties: false + BpdmTechnicalKeyData: + type: object + properties: + technicalKey: + type: string + name: + type: string + additionalProperties: false CertificateSorting: enum: - CertificateTypeAsc @@ -7441,6 +7757,77 @@ components: default: string nullable: true additionalProperties: false + PartnerNetworkData: + type: object + properties: + bpn: + type: string + legalName: + type: string + nullable: true + legalShortName: + type: string + nullable: true + currentness: + type: string + format: date-time + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time + identifiers: + type: array + items: + $ref: '#/components/schemas/BpdmIdentifierData' + legalForm: + $ref: '#/components/schemas/BpdmLegalFormData' + states: + type: array + items: + $ref: '#/components/schemas/BpdmStatusData' + confidenceCriteria: + $ref: '#/components/schemas/BpdmConfidenceCriteriaData' + isCatenaXMemberData: + type: boolean + relations: + type: array + items: + $ref: '#/components/schemas/BpdmRelationData' + legalEntityAddress: + $ref: '#/components/schemas/BpdmLegalEntityAddressData' + additionalProperties: false + PartnerNetworkRequest: + type: object + properties: + bpnls: + type: array + items: + type: string + legalName: + type: string + additionalProperties: false + PartnerNetworkResponse: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/PartnerNetworkData' + contentSize: + type: integer + format: int32 + page: + type: integer + format: int32 + totalElements: + type: integer + format: int32 + totalPages: + type: integer + format: int32 + additionalProperties: false PartnerRegistrationData: type: object properties: diff --git a/src/administration/Administration.Service/Program.cs b/src/administration/Administration.Service/Program.cs index c6ff2b4058..88b97e6d48 100644 --- a/src/administration/Administration.Service/Program.cs +++ b/src/administration/Administration.Service/Program.cs @@ -81,8 +81,6 @@ await WebAppHelper builder.Services.AddApplicationChecklist(builder.Configuration.GetSection("ApplicationChecklist")) .AddOfferSubscriptionProcess(); - builder.Services.AddBpnAccess(builder.Configuration.GetValue("BPN_Address") ?? throw new ConfigurationException("BPN_Address is not configured")); - builder.Services.AddTransient() .ConfigureConnectorsSettings(builder.Configuration.GetSection("Connectors")); diff --git a/src/administration/Administration.Service/appsettings.json b/src/administration/Administration.Service/appsettings.json index f60d1a8d0f..55fa24eb0d 100644 --- a/src/administration/Administration.Service/appsettings.json +++ b/src/administration/Administration.Service/appsettings.json @@ -26,7 +26,6 @@ "Cors": { "AllowedOrigins": [] }, - "BPN_Address": "", "Keycloak": { "central": { "ConnectionString": "", diff --git a/src/externalsystems/Bpdm.Library/BpnAccess.cs b/src/externalsystems/Bpdm.Library/BpnAccess.cs index 60e9fee9fc..6fb5d118ef 100644 --- a/src/externalsystems/Bpdm.Library/BpnAccess.cs +++ b/src/externalsystems/Bpdm.Library/BpnAccess.cs @@ -56,7 +56,8 @@ public async Task FetchLegalEntityByBpn(string businessPartn public async Task FetchPartnerNetworkData(int page, int size, IEnumerable bpnl, string legalName, string token, CancellationToken cancellationToken) { - _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + using var httpClient = httpFactory.CreateClient(nameof(BpnAccess)); + httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); var uri = new UriBuilder { Path = $"members/legal-entities/search", @@ -68,7 +69,7 @@ public async Task FetchPartnerNetworkData(int page, int async ValueTask<(bool, string?)> CreateErrorMessage(HttpResponseMessage errorResponse) => (false, (await errorResponse.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None))); - var result = await _httpClient.PostAsync(uri.PathAndQuery.TrimStart('/'), content, cancellationToken) + var result = await httpClient.PostAsync(uri.PathAndQuery.TrimStart('/'), content, cancellationToken) .CatchingIntoServiceExceptionFor("fetch-partner-network", HttpAsyncResponseMessageExtension.RecoverOptions.INFRASTRUCTURE, CreateErrorMessage) .ConfigureAwait(false); try From fdc13eda9bbbd0ccc4a4f0524617b7bda0cb1b8c Mon Sep 17 00:00:00 2001 From: Tayyab Fayyaz Janjua Date: Tue, 22 Oct 2024 11:43:03 +0200 Subject: [PATCH 3/3] WRN: Fixed Disposable 'StringContent' --- src/externalsystems/Bpdm.Library/BpnAccess.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/externalsystems/Bpdm.Library/BpnAccess.cs b/src/externalsystems/Bpdm.Library/BpnAccess.cs index 6fb5d118ef..6860463156 100644 --- a/src/externalsystems/Bpdm.Library/BpnAccess.cs +++ b/src/externalsystems/Bpdm.Library/BpnAccess.cs @@ -64,7 +64,7 @@ public async Task FetchPartnerNetworkData(int page, int Query = $"page={page}&size={size}" }.Uri; var request = new BpdmPartnerNetworkRequest(bpnl, legalName); - var content = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json"); + using var content = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json"); async ValueTask<(bool, string?)> CreateErrorMessage(HttpResponseMessage errorResponse) => (false, (await errorResponse.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None)));