diff --git a/src/Portal.Backend.sln b/src/Portal.Backend.sln index 0d0f6ae60d..b940cc935a 100644 --- a/src/Portal.Backend.sln +++ b/src/Portal.Backend.sln @@ -284,6 +284,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UserProvisioning.Executor.T EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SelfDescriptionCreation.Executor", "processes\SelfDescriptionCreation.Executor\SelfDescriptionCreation.Executor.csproj", "{08535520-F6E6-4DAF-AB36-12C48437368A}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SelfDescriptionCreation.Executor.Tests", "..\tests\processes\SelfDescriptionCreation.Executor.Tests\SelfDescriptionCreation.Executor.Tests.csproj", "{E87898BA-59A4-4F02-9594-50756BBF4E22}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1808,6 +1810,18 @@ Global {08535520-F6E6-4DAF-AB36-12C48437368A}.Release|x64.Build.0 = Release|Any CPU {08535520-F6E6-4DAF-AB36-12C48437368A}.Release|x86.ActiveCfg = Release|Any CPU {08535520-F6E6-4DAF-AB36-12C48437368A}.Release|x86.Build.0 = Release|Any CPU + {E87898BA-59A4-4F02-9594-50756BBF4E22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E87898BA-59A4-4F02-9594-50756BBF4E22}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E87898BA-59A4-4F02-9594-50756BBF4E22}.Debug|x64.ActiveCfg = Debug|Any CPU + {E87898BA-59A4-4F02-9594-50756BBF4E22}.Debug|x64.Build.0 = Debug|Any CPU + {E87898BA-59A4-4F02-9594-50756BBF4E22}.Debug|x86.ActiveCfg = Debug|Any CPU + {E87898BA-59A4-4F02-9594-50756BBF4E22}.Debug|x86.Build.0 = Debug|Any CPU + {E87898BA-59A4-4F02-9594-50756BBF4E22}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E87898BA-59A4-4F02-9594-50756BBF4E22}.Release|Any CPU.Build.0 = Release|Any CPU + {E87898BA-59A4-4F02-9594-50756BBF4E22}.Release|x64.ActiveCfg = Release|Any CPU + {E87898BA-59A4-4F02-9594-50756BBF4E22}.Release|x64.Build.0 = Release|Any CPU + {E87898BA-59A4-4F02-9594-50756BBF4E22}.Release|x86.ActiveCfg = Release|Any CPU + {E87898BA-59A4-4F02-9594-50756BBF4E22}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1943,5 +1957,6 @@ Global {9636BEC8-6929-4852-8DC8-8B41609630A3} = {282CEF03-292F-4A49-83C6-997567D0FF5F} {E5494227-BDFE-41F2-A12F-54292D76C29F} = {282CEF03-292F-4A49-83C6-997567D0FF5F} {08535520-F6E6-4DAF-AB36-12C48437368A} = {282CEF03-292F-4A49-83C6-997567D0FF5F} + {E87898BA-59A4-4F02-9594-50756BBF4E22} = {323C198D-A8C6-4EB0-8B79-72624275E35F} EndGlobalSection EndGlobal diff --git a/src/administration/Administration.Service/BusinessLogic/CompanyDataBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/CompanyDataBusinessLogic.cs index 2ec35d7c94..fc8a9b769f 100644 --- a/src/administration/Administration.Service/BusinessLogic/CompanyDataBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/CompanyDataBusinessLogic.cs @@ -439,4 +439,18 @@ public async Task DeleteCompanyCertificateAsync(Guid documentId) return (documentDetails.FileName, documentDetails.Content, documentDetails.MediaTypeId.MapToMediaType()); } + + public async Task TriggerSelfDescriptionCreation() + { + var hasMissingSdDocumentCompanies = await portalRepositories.GetInstance().HasAnyCompaniesWithMissingSelfDescription().ConfigureAwait(ConfigureAwaitOptions.None); + if (hasMissingSdDocumentCompanies) + { + var processStepRepository = portalRepositories.GetInstance(); + var processId = processStepRepository.CreateProcess(ProcessTypeId.SELF_DESCRIPTION_CREATION).Id; + + processStepRepository.CreateProcessStep(ProcessStepTypeId.SELF_DESCRIPTION_COMPANY_CREATION, ProcessStepStatusId.TODO, processId); + + await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); + } + } } diff --git a/src/administration/Administration.Service/BusinessLogic/ConnectorsBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/ConnectorsBusinessLogic.cs index fea70bff41..9828763d6d 100644 --- a/src/administration/Administration.Service/BusinessLogic/ConnectorsBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/ConnectorsBusinessLogic.cs @@ -107,11 +107,6 @@ private async Task CreateConnectorInternalAsync(ConnectorInputModel connec throw UnexpectedConditionException.Create(AdministrationConnectorErrors.CONNECTOR_UNEXPECTED_NO_BPN_ASSIGNED, new ErrorParameter[] { new("companyId", companyId.ToString()) }); } - if (result.SelfDescriptionDocumentId is null) - { - throw UnexpectedConditionException.Create(AdministrationConnectorErrors.CONNECTOR_UNEXPECTED_NO_DESCRIPTION, new ErrorParameter[] { new("companyId", companyId.ToString()) }); - } - await ValidateTechnicalUser(technicalUserId, companyId).ConfigureAwait(ConfigureAwaitOptions.None); var connectorRequestModel = new ConnectorRequestModel(name, connectorUrl, ConnectorTypeId.COMPANY_CONNECTOR, location, companyId, companyId, technicalUserId); @@ -435,4 +430,17 @@ public IAsyncEnumerable GetConnectorOfferSubscri size, _settings.MaxPageSize, portalRepositories.GetInstance().GetConnectorsWithMissingSdDocument()); + + public async Task TriggerSelfDescriptionCreation() + { + var hasMissingSdDocumentConnectors = await portalRepositories.GetInstance().HasAnyConnectorsWithMissingSelfDescription().ConfigureAwait(ConfigureAwaitOptions.None); + if (hasMissingSdDocumentConnectors) + { + var processStepRepository = portalRepositories.GetInstance(); + var processId = processStepRepository.CreateProcess(ProcessTypeId.SELF_DESCRIPTION_CREATION).Id; + processStepRepository.CreateProcessStep(ProcessStepTypeId.SELF_DESCRIPTION_CONNECTOR_CREATION, ProcessStepStatusId.TODO, processId); + + await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); + } + } } diff --git a/src/administration/Administration.Service/BusinessLogic/ICompanyDataBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/ICompanyDataBusinessLogic.cs index b38c91e781..05ea8fe4bc 100644 --- a/src/administration/Administration.Service/BusinessLogic/ICompanyDataBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/ICompanyDataBusinessLogic.cs @@ -53,4 +53,5 @@ public interface ICompanyDataBusinessLogic Task> GetAllCompanyCertificatesAsync(int page, int size, CertificateSorting? sorting, CompanyCertificateStatusId? certificateStatus, CompanyCertificateTypeId? certificateType); Task GetDimServiceUrls(); Task> GetCompaniesWithMissingSdDocument(int page, int size); + Task TriggerSelfDescriptionCreation(); } diff --git a/src/administration/Administration.Service/BusinessLogic/IConnectorsBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/IConnectorsBusinessLogic.cs index fc49d383d7..0f92ba43cc 100644 --- a/src/administration/Administration.Service/BusinessLogic/IConnectorsBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/IConnectorsBusinessLogic.cs @@ -102,4 +102,6 @@ public interface IConnectorsBusinessLogic IAsyncEnumerable GetConnectorOfferSubscriptionData(bool? connectorIdSet); Task> GetConnectorsWithMissingSdDocument(int page, int size); + + Task TriggerSelfDescriptionCreation(); } diff --git a/src/administration/Administration.Service/BusinessLogic/IRegistrationBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/IRegistrationBusinessLogic.cs index 68786d3e32..1ce740c945 100644 --- a/src/administration/Administration.Service/BusinessLogic/IRegistrationBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/IRegistrationBusinessLogic.cs @@ -131,6 +131,4 @@ public interface IRegistrationBusinessLogic /// /// Id of the Process Task RetriggerDeleteCentralUser(Guid processId); - - Task TriggerSelfDescriptionCreation(); } diff --git a/src/administration/Administration.Service/BusinessLogic/RegistrationBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/RegistrationBusinessLogic.cs index f91f1c3a91..d036736815 100644 --- a/src/administration/Administration.Service/BusinessLogic/RegistrationBusinessLogic.cs +++ b/src/administration/Administration.Service/BusinessLogic/RegistrationBusinessLogic.cs @@ -339,7 +339,7 @@ private async Task UpdateCompanyBpnInternal(Guid applicationId, string bpn) /// public async Task ProcessClearinghouseResponseAsync(ClearinghouseResponseData data, CancellationToken cancellationToken) { - logger.LogInformation("Process SelfDescription called with the following data {Data}", data); + logger.LogInformation("Process SelfDescription called with the following data {Data}", data.ToString().Replace(Environment.NewLine, string.Empty)); var result = await portalRepositories.GetInstance().GetSubmittedApplicationIdsByBpn(data.BusinessPartnerNumber.ToUpper()).ToListAsync(cancellationToken).ConfigureAwait(false); if (!result.Any()) { @@ -358,7 +358,7 @@ public async Task ProcessClearinghouseResponseAsync(ClearinghouseResponseData da /// public async Task ProcessDimResponseAsync(string bpn, DimWalletData data, CancellationToken cancellationToken) { - logger.LogInformation("Process Dim called with the following data {Data}", data); + logger.LogInformation("Process Dim called with the following data {Data}", data.ToString().Replace(Environment.NewLine, string.Empty)); await dimBusinessLogic.ProcessDimResponse(bpn, data, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.None); await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); @@ -435,7 +435,7 @@ private async Task TriggerChecklistInternal(Guid applicationId, ApplicationCheck /// public async Task ProcessClearinghouseSelfDescription(SelfDescriptionResponseData data, CancellationToken cancellationToken) { - logger.LogInformation("Process SelfDescription called with the following data {Data}", data); + logger.LogInformation("Process SelfDescription called with the following data {Data}", data.ToString().Replace(Environment.NewLine, string.Empty)); var isExistingCompany = await portalRepositories.GetInstance().IsExistingCompany(data.ExternalId); if (isExistingCompany) @@ -701,27 +701,4 @@ private async Task RetriggerProcessStepInternal(Guid processId, ProcessStepTypeI context.FinalizeProcessStep(); await portalRepositories.SaveAsync().ConfigureAwait(false); } - - public async Task TriggerSelfDescriptionCreation() - { - var hasMissingSdDocumentCompanies = await portalRepositories.GetInstance().HasAnyCompaniesWithMissingSelfDescription().ConfigureAwait(ConfigureAwaitOptions.None); - var hasMissingSdDocumentConnectors = await portalRepositories.GetInstance().HasAnyConnectorsWithMissingSelfDescription().ConfigureAwait(ConfigureAwaitOptions.None); - if (hasMissingSdDocumentCompanies || hasMissingSdDocumentConnectors) - { - var processStepRepository = portalRepositories.GetInstance(); - var processId = processStepRepository.CreateProcess(ProcessTypeId.SELF_DESCRIPTION_CREATION).Id; - - if (hasMissingSdDocumentCompanies) - { - processStepRepository.CreateProcessStep(ProcessStepTypeId.SELF_DESCRIPTION_COMPANY_CREATION, ProcessStepStatusId.TODO, processId); - } - - if (hasMissingSdDocumentConnectors) - { - processStepRepository.CreateProcessStep(ProcessStepTypeId.SELF_DESCRIPTION_CONNECTOR_CREATION, ProcessStepStatusId.TODO, processId); - } - - await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None); - } - } } diff --git a/src/administration/Administration.Service/Controllers/CompanyDataController.cs b/src/administration/Administration.Service/Controllers/CompanyDataController.cs index 90a004a5a6..52d3676084 100644 --- a/src/administration/Administration.Service/Controllers/CompanyDataController.cs +++ b/src/administration/Administration.Service/Controllers/CompanyDataController.cs @@ -345,4 +345,24 @@ public Task GetDimServiceUrls() => [ProducesResponseType(typeof(Pagination.Response), StatusCodes.Status200OK)] public Task> GetCompaniesWithMissingSdDocument([FromQuery] int page = 0, [FromQuery] int size = 15) => logic.GetCompaniesWithMissingSdDocument(page, size); + + /// + /// Triggers the process to create the missing self description documents + /// + /// NoContent + /// Example: POST: /api/administration/companyData/trigger-self-description + /// Empty response on success. + /// No Process found for the processId + [HttpPost] + [Authorize(Roles = "approve_new_partner")] + [Authorize(Policy = PolicyTypes.CompanyUser)] + [Route("trigger-self-description")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] + public async Task TriggerSelfDescriptionProcess() + { + await logic.TriggerSelfDescriptionCreation().ConfigureAwait(false); + return NoContent(); + } } diff --git a/src/administration/Administration.Service/Controllers/ConnectorsController.cs b/src/administration/Administration.Service/Controllers/ConnectorsController.cs index 5aa28dd89e..168a7f1e9b 100644 --- a/src/administration/Administration.Service/Controllers/ConnectorsController.cs +++ b/src/administration/Administration.Service/Controllers/ConnectorsController.cs @@ -276,4 +276,24 @@ public IAsyncEnumerable GetConnectorOfferSubscri [ProducesResponseType(typeof(Pagination.Response), StatusCodes.Status200OK)] public Task> GetConnectorsWithMissingSdDocument([FromQuery] int page = 0, [FromQuery] int size = 15) => _businessLogic.GetConnectorsWithMissingSdDocument(page, size); + + /// + /// Triggers the process to create the missing self description documents + /// + /// NoContent + /// Example: POST: /api/administration/connectors/trigger-self-description + /// Empty response on success. + /// No Process found for the processId + [HttpPost] + [Authorize(Roles = "approve_new_partner")] + [Authorize(Policy = PolicyTypes.CompanyUser)] + [Route("trigger-self-description")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] + public async Task TriggerSelfDescriptionProcess() + { + await _businessLogic.TriggerSelfDescriptionCreation().ConfigureAwait(false); + return NoContent(); + } } diff --git a/src/administration/Administration.Service/Controllers/RegistrationController.cs b/src/administration/Administration.Service/Controllers/RegistrationController.cs index 4034cf3a74..6dfd31b77a 100644 --- a/src/administration/Administration.Service/Controllers/RegistrationController.cs +++ b/src/administration/Administration.Service/Controllers/RegistrationController.cs @@ -581,24 +581,4 @@ public async Task RetriggerDeleteCentralUser([FromRoute] Guid p [ProducesResponseType(typeof(Pagination.Response), StatusCodes.Status200OK)] public Task> GetOspCompanyDetailsAsync([FromQuery] int page, [FromQuery] int size, [FromQuery] CompanyApplicationStatusFilter? companyApplicationStatusFilter = null, [FromQuery] string? companyName = null) => _logic.GetOspCompanyDetailsAsync(page, size, companyApplicationStatusFilter, companyName); - - /// - /// Triggers the process to create the missing self description documents - /// - /// NoContent - /// Example: POST: api/administration/registration/trigger-self-description - /// Empty response on success. - /// No Process found for the processId - [HttpPost] - [Authorize(Roles = "approve_new_partner")] - [Authorize(Policy = PolicyTypes.CompanyUser)] - [Route("trigger-self-description")] - [ProducesResponseType(StatusCodes.Status204NoContent)] - [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)] - [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)] - public async Task TriggerSelfDescriptionProcess() - { - await _logic.TriggerSelfDescriptionCreation().ConfigureAwait(false); - return NoContent(); - } } diff --git a/src/externalsystems/Custodian.Library/BusinessLogic/CustodianBusinessLogic.cs b/src/externalsystems/Custodian.Library/BusinessLogic/CustodianBusinessLogic.cs index 8b034a8eec..edd7e5c4f1 100644 --- a/src/externalsystems/Custodian.Library/BusinessLogic/CustodianBusinessLogic.cs +++ b/src/externalsystems/Custodian.Library/BusinessLogic/CustodianBusinessLogic.cs @@ -23,6 +23,9 @@ using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; using Org.Eclipse.TractusX.Portal.Backend.Processes.ApplicationChecklist.Library; +using System; +using System.Threading; +using System.Threading.Tasks; namespace Org.Eclipse.TractusX.Portal.Backend.Custodian.Library.BusinessLogic; diff --git a/src/externalsystems/Custodian.Library/BusinessLogic/ICustodianBusinessLogic.cs b/src/externalsystems/Custodian.Library/BusinessLogic/ICustodianBusinessLogic.cs index 67fdab9252..5dcabea91d 100644 --- a/src/externalsystems/Custodian.Library/BusinessLogic/ICustodianBusinessLogic.cs +++ b/src/externalsystems/Custodian.Library/BusinessLogic/ICustodianBusinessLogic.cs @@ -20,6 +20,9 @@ using Org.Eclipse.TractusX.Portal.Backend.Custodian.Library.Models; using Org.Eclipse.TractusX.Portal.Backend.Processes.ApplicationChecklist.Library; +using System; +using System.Threading; +using System.Threading.Tasks; namespace Org.Eclipse.TractusX.Portal.Backend.Custodian.Library.BusinessLogic; diff --git a/src/externalsystems/Custodian.Library/CustodianService.cs b/src/externalsystems/Custodian.Library/CustodianService.cs index a3bf36fd67..1a821881bc 100644 --- a/src/externalsystems/Custodian.Library/CustodianService.cs +++ b/src/externalsystems/Custodian.Library/CustodianService.cs @@ -27,8 +27,11 @@ using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; using System.Net; +using System.Net.Http; using System.Net.Http.Json; using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; namespace Org.Eclipse.TractusX.Portal.Backend.Custodian.Library; diff --git a/src/externalsystems/Custodian.Library/ICustodianService.cs b/src/externalsystems/Custodian.Library/ICustodianService.cs index 36421193c0..7d7ce536a8 100644 --- a/src/externalsystems/Custodian.Library/ICustodianService.cs +++ b/src/externalsystems/Custodian.Library/ICustodianService.cs @@ -22,6 +22,8 @@ using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; +using System.Threading; +using System.Threading.Tasks; namespace Org.Eclipse.TractusX.Portal.Backend.Custodian.Library; diff --git a/src/externalsystems/Custodian.Library/Models/WalletErrorResponse.cs b/src/externalsystems/Custodian.Library/Models/WalletErrorResponse.cs index e3529f1872..66748c9ed0 100644 --- a/src/externalsystems/Custodian.Library/Models/WalletErrorResponse.cs +++ b/src/externalsystems/Custodian.Library/Models/WalletErrorResponse.cs @@ -18,6 +18,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +using System; using System.Text.Json.Serialization; namespace Org.Eclipse.TractusX.Portal.Backend.Custodian.Library.Models; diff --git a/src/externalsystems/Custodian.Library/Models/WalletListItem.cs b/src/externalsystems/Custodian.Library/Models/WalletListItem.cs index 7c5547a40e..7887f68c02 100644 --- a/src/externalsystems/Custodian.Library/Models/WalletListItem.cs +++ b/src/externalsystems/Custodian.Library/Models/WalletListItem.cs @@ -18,6 +18,7 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +using System; using System.Text.Json.Serialization; namespace Org.Eclipse.TractusX.Portal.Backend.Custodian.Library.Models; diff --git a/src/portalbackend/PortalBackend.DBAccess/Models/CompanyMissingSdDocumentData.cs b/src/portalbackend/PortalBackend.DBAccess/Models/CompanyMissingSdDocumentData.cs index 9369715874..a04473d2a1 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Models/CompanyMissingSdDocumentData.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Models/CompanyMissingSdDocumentData.cs @@ -20,6 +20,6 @@ namespace Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models; public record CompanyMissingSdDocumentData( - Guid Id, + Guid CompanyId, string Name ); diff --git a/src/portalbackend/PortalBackend.DBAccess/Models/ConnectorData.cs b/src/portalbackend/PortalBackend.DBAccess/Models/ConnectorData.cs index f7f10086f9..54451cf40b 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Models/ConnectorData.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Models/ConnectorData.cs @@ -80,4 +80,4 @@ public record ConnectorOfferSubscription(Guid AssignedOfferSubscriptionIds, Offe public record TechnicalUserData(Guid Id, string Name, string? ClientId, string Description); -public record ConnectorMissingSdDocumentData(Guid Id, string Name, Guid CompanyId, string CompanyName); +public record ConnectorMissingSdDocumentData(Guid ConnectorId, string Name, Guid CompanyId, string CompanyName); diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/CompanyRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/CompanyRepository.cs index 25e247e6d4..dd86c9de69 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/CompanyRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/CompanyRepository.cs @@ -417,8 +417,15 @@ public void RemoveProviderCompanyDetails(Guid providerCompanyDetailId) => skip, take, context.Companies.AsNoTracking() - .Where(x => x.CompanyStatusId == CompanyStatusId.ACTIVE && x.SelfDescriptionDocumentId == null) - .GroupBy(c => c.AddressId), + .Where(c => + c.CompanyStatusId == CompanyStatusId.ACTIVE && + c.SelfDescriptionDocumentId == null && + c.CompanyApplications.Any(ca => + ca.ApplicationChecklistEntries.Any(a => + a.ApplicationChecklistEntryTypeId == ApplicationChecklistEntryTypeId.SELF_DESCRIPTION_LP && + a.ApplicationChecklistEntryStatusId != ApplicationChecklistEntryStatusId.TO_DO && + a.ApplicationChecklistEntryStatusId != ApplicationChecklistEntryStatusId.IN_PROGRESS))) + .GroupBy(c => c.CompanyStatusId), c => c.OrderByDescending(company => company.Name), c => new CompanyMissingSdDocumentData( c.Id, @@ -427,6 +434,7 @@ public void RemoveProviderCompanyDetails(Guid providerCompanyDetailId) => public Task HasAnyCompaniesWithMissingSelfDescription() => context.Companies.AnyAsync(c => + c.CompanyStatusId == CompanyStatusId.ACTIVE && c.SelfDescriptionDocumentId == null && c.CompanyApplications.Any(ca => ca.ApplicationChecklistEntries.Any(a => @@ -436,6 +444,7 @@ public Task HasAnyCompaniesWithMissingSelfDescription() => public IAsyncEnumerable<(Guid Id, IEnumerable<(UniqueIdentifierId Id, string Value)> UniqueIdentifiers, string? BusinessPartnerNumber, string CountryCode)> GetCompaniesWithMissingSelfDescription() => context.Companies.Where(c => + c.CompanyStatusId == CompanyStatusId.ACTIVE && c.SelfDescriptionDocumentId == null && c.CompanyApplications.Any(ca => ca.ApplicationChecklistEntries.Any(a => diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/ConnectorsRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/ConnectorsRepository.cs index e127cf9bfa..bf1497355e 100644 --- a/src/portalbackend/PortalBackend.DBAccess/Repositories/ConnectorsRepository.cs +++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/ConnectorsRepository.cs @@ -211,7 +211,7 @@ public void DeleteConnectorAssignedSubscriptions(Guid connectorId, IEnumerable x.StatusId == ConnectorStatusId.ACTIVE && x.SelfDescriptionDocumentId == null) - .GroupBy(c => c.ProviderId), + .GroupBy(c => c.StatusId), connector => connector.OrderByDescending(c => c.Name), con => new ConnectorMissingSdDocumentData( con.Id, @@ -225,7 +225,7 @@ public Task HasAnyConnectorsWithMissingSelfDescription() => public IAsyncEnumerable<(Guid Id, string? BusinessPartnerNumber, Guid? SelfDescriptionDocumentId)> GetConnectorsWithMissingSelfDescription() => _context.Connectors - .Where(c => c.SelfDescriptionDocumentId == null) + .Where(c => c.StatusId == ConnectorStatusId.ACTIVE && c.SelfDescriptionDocumentId == null) .Select(c => new ValueTuple(c.Id, c.Provider!.BusinessPartnerNumber, c.Provider.SelfDescriptionDocumentId)) .ToAsyncEnumerable(); } diff --git a/src/processes/SelfDescriptionCreation.Executor/SdCreationProcessTypeExecutor.cs b/src/processes/SelfDescriptionCreation.Executor/SdCreationProcessTypeExecutor.cs index 8d7d88eae3..003db9edcb 100644 --- a/src/processes/SelfDescriptionCreation.Executor/SdCreationProcessTypeExecutor.cs +++ b/src/processes/SelfDescriptionCreation.Executor/SdCreationProcessTypeExecutor.cs @@ -111,7 +111,7 @@ await sdFactoryService.RegisterSelfDescriptionAsync(id, uniqueIdentifiers, count } var selfDescriptionDocumentUrl = $"{_settings.SelfDescriptionDocumentUrl}/{selfDescriptionDocumentId}"; - await sdFactoryService.RegisterConnectorAsync(id, businessPartnerNumber, selfDescriptionDocumentUrl, cancellationToken) + await sdFactoryService.RegisterConnectorAsync(id, selfDescriptionDocumentUrl, businessPartnerNumber, cancellationToken) .ConfigureAwait(ConfigureAwaitOptions.None); var nextStepTypeIds = await enumerator.MoveNextAsync().ConfigureAwait(false) diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/CompanyDataBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/CompanyDataBusinessLogicTests.cs index 5ddbe66846..f4e7fb44cb 100644 --- a/tests/administration/Administration.Service.Tests/BusinessLogic/CompanyDataBusinessLogicTests.cs +++ b/tests/administration/Administration.Service.Tests/BusinessLogic/CompanyDataBusinessLogicTests.cs @@ -46,6 +46,7 @@ public class CompanyDataBusinessLogicTests private readonly IConsentRepository _consentRepository; private readonly ICompanyRepository _companyRepository; private readonly ICompanyRolesRepository _companyRolesRepository; + private readonly IProcessStepRepository _processStepRepository; private readonly IDocumentRepository _documentRepository; private readonly ILanguageRepository _languageRepository; private readonly ICompanyCertificateRepository _companyCertificateRepository; @@ -65,6 +66,7 @@ public CompanyDataBusinessLogicTests() _documentRepository = A.Fake(); _languageRepository = A.Fake(); _companyCertificateRepository = A.Fake(); + _processStepRepository = A.Fake(); var issuerComponentBusinessLogic = A.Fake(); _now = _fixture.Create(); @@ -80,6 +82,7 @@ public CompanyDataBusinessLogicTests() A.CallTo(() => _portalRepositories.GetInstance()).Returns(_documentRepository); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_languageRepository); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_companyCertificateRepository); + A.CallTo(() => _portalRepositories.GetInstance()).Returns(_processStepRepository); A.CallTo(() => _identity.IdentityId).Returns(Guid.NewGuid()); A.CallTo(() => _identity.IdentityTypeId).Returns(IdentityTypeId.COMPANY_USER); @@ -1072,6 +1075,38 @@ public async Task GetCompanyCertificateDocumentAsync_WithDocumentStatusIsNotLock #endregion + #region GetCompaniesWithMissingSdDocument + + [Fact] + public async Task GetCompaniesWithMissingSdDocument_WithMoreData_ReturnsExpected() + { + // Arrange + SetupFakesForGetMissingSdDocCompanies(15); + + // Act + var result = await _sut.GetCompaniesWithMissingSdDocument(0, 10); + + // Assert + result.Should().NotBeNull(); + result.Content.Count().Should().Be(10); + } + + [Fact] + public async Task GetCompaniesWithMissingSdDocument_WithLessData_ReturnsExpected() + { + // Arrange + SetupFakesForGetMissingSdDocCompanies(7); + + // Act + var result = await _sut.GetCompaniesWithMissingSdDocument(0, 10); + + // Assert + result.Should().NotBeNull(); + result.Content.Count().Should().Be(7); + } + + #endregion + #region DeleteCompanyCertificates [Fact] @@ -1204,6 +1239,74 @@ public async Task GetDimServiceUrls_WithoutWalletUrl_ThrowsConflictException() #endregion + #region TriggerSelfDescriptionCreation + + [Fact] + public async Task TriggerSelfDescriptionCreation_WithMissingSdDocsForConnectorAndCompany_CallsExpected() + { + // Arrange + var processId = Guid.NewGuid(); + var processes = new List(); + var processSteps = new List(); + A.CallTo(() => _processStepRepository.CreateProcess(A._)) + .Invokes((ProcessTypeId processTypeId) => + { + processes.Add(new Process(processId, processTypeId, Guid.NewGuid())); + }) + .Returns(new Process(processId, default, default)); + A.CallTo(() => _processStepRepository.CreateProcessStep(A._, A._, processId)) + .Invokes((ProcessStepTypeId processStepTypeId, ProcessStepStatusId processStepStatusId, Guid _) => + { + processSteps.Add(new ProcessStep(Guid.NewGuid(), processStepTypeId, processStepStatusId, processId, DateTimeOffset.UtcNow)); + }); + A.CallTo(() => _companyRepository.HasAnyCompaniesWithMissingSelfDescription()) + .Returns(true); + + // Act + await _sut.TriggerSelfDescriptionCreation(); + + // Assert + processes.Should().NotBeNull() + .And.ContainSingle() + .Which.ProcessTypeId.Should().Be(ProcessTypeId.SELF_DESCRIPTION_CREATION); + processSteps.Should().NotBeNull().And.HaveCount(1) + .And.Satisfy( + p => p.ProcessStepTypeId == ProcessStepTypeId.SELF_DESCRIPTION_COMPANY_CREATION); + A.CallTo(() => _portalRepositories.SaveAsync()).MustHaveHappenedOnceExactly(); + } + + [Fact] + public async Task TriggerSelfDescriptionCreation_WithoutMissingSdDocsForCompany_CallsExpected() + { + // Arrange + var processId = Guid.NewGuid(); + var processes = new List(); + var processSteps = new List(); + A.CallTo(() => _processStepRepository.CreateProcess(A._)) + .Invokes((ProcessTypeId processTypeId) => + { + processes.Add(new Process(processId, processTypeId, Guid.NewGuid())); + }) + .Returns(new Process(processId, default, default)); + A.CallTo(() => _processStepRepository.CreateProcessStep(A._, A._, processId)) + .Invokes((ProcessStepTypeId processStepTypeId, ProcessStepStatusId processStepStatusId, Guid _) => + { + processSteps.Add(new ProcessStep(Guid.NewGuid(), processStepTypeId, processStepStatusId, processId, DateTimeOffset.UtcNow)); + }); + A.CallTo(() => _companyRepository.HasAnyCompaniesWithMissingSelfDescription()) + .Returns(false); + + // Act + await _sut.TriggerSelfDescriptionCreation(); + + // Assert + processes.Should().BeEmpty(); + processSteps.Should().BeEmpty(); + A.CallTo(() => _portalRepositories.SaveAsync()).MustNotHaveHappened(); + } + + #endregion + #region Setup private void SetupCreateCompanyCertificate() @@ -1236,5 +1339,14 @@ private void SetupFakesForGetDocument() .ReturnsLazily(() => new ValueTuple(content, "test1.pdf", MediaTypeId.PDF, true, false)); } + private void SetupFakesForGetMissingSdDocCompanies(int count = 5) + { + var companyMissingSdDocumentData = _fixture.CreateMany(count); + var paginationResult = (int skip, int take) => Task.FromResult(new Pagination.Source(companyMissingSdDocumentData.Count(), companyMissingSdDocumentData.Skip(skip).Take(take))); + + A.CallTo(() => _companyRepository.GetCompaniesWithMissingSdDocument())! + .Returns(paginationResult); + } + #endregion } diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/ConnectorsBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/ConnectorsBusinessLogicTests.cs index 5c5395501d..222042dc82 100644 --- a/tests/administration/Administration.Service.Tests/BusinessLogic/ConnectorsBusinessLogicTests.cs +++ b/tests/administration/Administration.Service.Tests/BusinessLogic/ConnectorsBusinessLogicTests.cs @@ -61,6 +61,7 @@ public class ConnectorsBusinessLogicTests private readonly ConnectorsBusinessLogic _logic; private readonly IDocumentRepository _documentRepository; private readonly IServiceAccountRepository _serviceAccountRepository; + private readonly IProcessStepRepository _processStepRepository; private readonly IOptions _options; private readonly IIdentityService _identityService; @@ -77,6 +78,7 @@ public ConnectorsBusinessLogicTests() _sdFactoryBusinessLogic = A.Fake(); _serviceAccountRepository = A.Fake(); _offerSubscriptionRepository = A.Fake(); + _processStepRepository = A.Fake(); _identityService = A.Fake(); _identity = A.Fake(); _connectors = new List(); @@ -1215,6 +1217,106 @@ public async Task GetCompanyConnectorData_WithValid_ReturnsExpected() #endregion + #region GetConnectorsWithMissingSdDocument + + [Fact] + public async Task GetConnectorsWithMissingSdDocument_WithMoreData_ReturnsExpected() + { + // Arrange + SetupFakesForGetMissingSdDocConnectors(15); + + // Act + var result = await _logic.GetConnectorsWithMissingSdDocument(0, 10); + + // Assert + result.Should().NotBeNull(); + result.Content.Count().Should().Be(10); + } + + [Fact] + public async Task GetConnectorsWithMissingSdDocument_WithLessData_ReturnsExpected() + { + // Arrange + SetupFakesForGetMissingSdDocConnectors(7); + + // Act + var result = await _logic.GetConnectorsWithMissingSdDocument(0, 10); + + // Assert + result.Should().NotBeNull(); + result.Content.Count().Should().Be(7); + } + + #endregion + + #region TriggerSelfDescriptionCreation + + [Fact] + public async Task TriggerSelfDescriptionCreation_WithMissingSdDocsForConnector_CallsExpected() + { + // Arrange + var processId = Guid.NewGuid(); + var processes = new List(); + var processSteps = new List(); + A.CallTo(() => _processStepRepository.CreateProcess(A._)) + .Invokes((ProcessTypeId processTypeId) => + { + processes.Add(new Process(processId, processTypeId, Guid.NewGuid())); + }) + .Returns(new Process(processId, default, default)); + A.CallTo(() => _processStepRepository.CreateProcessStep(A._, A._, processId)) + .Invokes((ProcessStepTypeId processStepTypeId, ProcessStepStatusId processStepStatusId, Guid _) => + { + processSteps.Add(new ProcessStep(Guid.NewGuid(), processStepTypeId, processStepStatusId, processId, DateTimeOffset.UtcNow)); + }); + A.CallTo(() => _connectorsRepository.HasAnyConnectorsWithMissingSelfDescription()) + .Returns(true); + + // Act + await _logic.TriggerSelfDescriptionCreation(); + + // Assert + processes.Should().NotBeNull() + .And.ContainSingle() + .Which.ProcessTypeId.Should().Be(ProcessTypeId.SELF_DESCRIPTION_CREATION); + processSteps.Should().NotBeNull().And.HaveCount(1) + .And.Satisfy( + p => p.ProcessStepTypeId == ProcessStepTypeId.SELF_DESCRIPTION_CONNECTOR_CREATION); + A.CallTo(() => _portalRepositories.SaveAsync()).MustHaveHappenedOnceExactly(); + } + + [Fact] + public async Task TriggerSelfDescriptionCreation_WithoutMissingSdDocsForConnector_CallsExpected() + { + // Arrange + var processId = Guid.NewGuid(); + var processes = new List(); + var processSteps = new List(); + A.CallTo(() => _processStepRepository.CreateProcess(A._)) + .Invokes((ProcessTypeId processTypeId) => + { + processes.Add(new Process(processId, processTypeId, Guid.NewGuid())); + }) + .Returns(new Process(processId, default, default)); + A.CallTo(() => _processStepRepository.CreateProcessStep(A._, A._, processId)) + .Invokes((ProcessStepTypeId processStepTypeId, ProcessStepStatusId processStepStatusId, Guid _) => + { + processSteps.Add(new ProcessStep(Guid.NewGuid(), processStepTypeId, processStepStatusId, processId, DateTimeOffset.UtcNow)); + }); + A.CallTo(() => _companyRepository.HasAnyCompaniesWithMissingSelfDescription()) + .Returns(false); + + // Act + await _logic.TriggerSelfDescriptionCreation(); + + // Assert + processes.Should().BeEmpty(); + processSteps.Should().BeEmpty(); + A.CallTo(() => _portalRepositories.SaveAsync()).MustNotHaveHappened(); + } + + #endregion + #region Setup private void SetupRepositoryMethods() @@ -1270,6 +1372,7 @@ private void SetupRepositoryMethods() A.CallTo(() => _portalRepositories.GetInstance()).Returns(_userRepository); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_documentRepository); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_offerSubscriptionRepository); + A.CallTo(() => _portalRepositories.GetInstance()).Returns(_processStepRepository); } private void SetupIdentity() @@ -1285,5 +1388,14 @@ private void SetupTechnicalIdentity() A.CallTo(() => _identity.IdentityTypeId).Returns(IdentityTypeId.COMPANY_SERVICE_ACCOUNT); } + private void SetupFakesForGetMissingSdDocConnectors(int count = 5) + { + var companyMissingSdDocumentData = _fixture.CreateMany(count); + var paginationResult = (int skip, int take) => Task.FromResult(new Pagination.Source(companyMissingSdDocumentData.Count(), companyMissingSdDocumentData.Skip(skip).Take(take))); + + A.CallTo(() => _connectorsRepository.GetConnectorsWithMissingSdDocument())! + .Returns(paginationResult); + } + #endregion } diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/RegistrationBusinessLogicTest.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/RegistrationBusinessLogicTest.cs index 3b5db39d95..7de75707cb 100644 --- a/tests/administration/Administration.Service.Tests/BusinessLogic/RegistrationBusinessLogicTest.cs +++ b/tests/administration/Administration.Service.Tests/BusinessLogic/RegistrationBusinessLogicTest.cs @@ -74,6 +74,7 @@ public class RegistrationBusinessLogicTest private readonly IFixture _fixture; private readonly IRegistrationBusinessLogic _logic; private readonly ICompanyRepository _companyRepository; + private readonly IConnectorsRepository _connectorRepository; private readonly IApplicationChecklistService _checklistService; private readonly IClearinghouseBusinessLogic _clearinghouseBusinessLogic; private readonly ISdFactoryBusinessLogic _sdFactoryBusinessLogic; @@ -96,6 +97,7 @@ public RegistrationBusinessLogicTest() _processStepRepository = A.Fake(); _userRepository = A.Fake(); _companyRepository = A.Fake(); + _connectorRepository = A.Fake(); _mailingProcessCreation = A.Fake(); _options = A.Fake>(); @@ -117,6 +119,7 @@ public RegistrationBusinessLogicTest() A.CallTo(() => _portalRepositories.GetInstance()).Returns(_documentRepository); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_userRepository); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_companyRepository); + A.CallTo(() => _portalRepositories.GetInstance()).Returns(_connectorRepository); A.CallTo(() => _portalRepositories.GetInstance()).Returns(_processStepRepository); A.CallTo(() => _identityData.IdentityId).Returns(Guid.NewGuid()); @@ -810,6 +813,8 @@ public async Task ProcessClearinghouseSelfDescription_WithValidData_CallsExpecte // Arrange var data = new SelfDescriptionResponseData(ApplicationId, SelfDescriptionStatus.Confirm, null, "{ \"test\": true }"); var companyId = Guid.NewGuid(); + A.CallTo(() => _companyRepository.IsExistingCompany(CompanyId)) + .Returns(false); A.CallTo(() => _applicationRepository.GetCompanyIdSubmissionStatusForApplication(ApplicationId)) .Returns((true, companyId, true)); @@ -819,6 +824,25 @@ public async Task ProcessClearinghouseSelfDescription_WithValidData_CallsExpecte // Assert A.CallTo(() => _sdFactoryBusinessLogic.ProcessFinishSelfDescriptionLpForApplication(data, companyId, A._)) .MustHaveHappenedOnceExactly(); + A.CallTo(() => _sdFactoryBusinessLogic.ProcessFinishSelfDescriptionLpForCompany(A._, A._)) + .MustNotHaveHappened(); + A.CallTo(() => _portalRepositories.SaveAsync()).MustHaveHappenedOnceExactly(); + } + + [Fact] + public async Task ProcessClearinghouseSelfDescription_WithValidCompany_CallsExpected() + { + // Arrange + var data = new SelfDescriptionResponseData(CompanyId, SelfDescriptionStatus.Confirm, null, "{ \"test\": true }"); + A.CallTo(() => _companyRepository.IsExistingCompany(CompanyId)) + .Returns(true); + + // Act + await _logic.ProcessClearinghouseSelfDescription(data, CancellationToken.None); + + // Assert + A.CallTo(() => _sdFactoryBusinessLogic.ProcessFinishSelfDescriptionLpForCompany(data, A._)) + .MustHaveHappenedOnceExactly(); A.CallTo(() => _portalRepositories.SaveAsync()).MustHaveHappenedOnceExactly(); } @@ -829,6 +853,8 @@ public async Task ProcessClearinghouseSelfDescription_WithNotExistingApplication var data = new SelfDescriptionResponseData(ApplicationId, SelfDescriptionStatus.Confirm, null, "{ \"test\": true }"); A.CallTo(() => _applicationRepository.GetCompanyIdSubmissionStatusForApplication(ApplicationId)) .Returns<(bool, Guid, bool)>(default); + A.CallTo(() => _companyRepository.IsExistingCompany(CompanyId)) + .Returns(false); // Act Task Act() => _logic.ProcessClearinghouseSelfDescription(data, CancellationToken.None); @@ -845,6 +871,8 @@ public async Task ProcessClearinghouseSelfDescription_WithNotSubmittedApplicatio var data = new SelfDescriptionResponseData(ApplicationId, SelfDescriptionStatus.Confirm, null, "{ \"test\": true }"); A.CallTo(() => _applicationRepository.GetCompanyIdSubmissionStatusForApplication(ApplicationId)) .Returns((true, Guid.NewGuid(), false)); + A.CallTo(() => _companyRepository.IsExistingCompany(CompanyId)) + .Returns(false); // Act Task Act() => _logic.ProcessClearinghouseSelfDescription(data, CancellationToken.None); diff --git a/tests/administration/Administration.Service.Tests/Controllers/CompanyDataControllerTests.cs b/tests/administration/Administration.Service.Tests/Controllers/CompanyDataControllerTests.cs index 657c1475d2..9c7b652bf2 100644 --- a/tests/administration/Administration.Service.Tests/Controllers/CompanyDataControllerTests.cs +++ b/tests/administration/Administration.Service.Tests/Controllers/CompanyDataControllerTests.cs @@ -187,4 +187,30 @@ public async Task GetDimServiceUrls() result.DecentralIdentityManagementAuthUrl.Should().Be(decentralIdentityManagementAuthUrl); result.DecentralIdentityManagementServiceUrl.Should().Be(decentralIdentityManagementServiceUrl); } + + [Fact] + public async Task GetCompaniesWithMissingSdDocument() + { + // Arrange + var paginationResponse = new Pagination.Response(new Pagination.Metadata(15, 1, 1, 15), _fixture.CreateMany(5)); + A.CallTo(() => _logic.GetCompaniesWithMissingSdDocument(A._, A._)) + .Returns(paginationResponse); + + //Act + var result = await _controller.GetCompaniesWithMissingSdDocument(); + + //Assert + result.Content.Should().HaveCount(5); + } + + [Fact] + public async Task TriggerSelfDescriptionProcess_CallsExpected() + { + // Act + var result = await _controller.TriggerSelfDescriptionProcess(); + + // Assert + A.CallTo(() => _logic.TriggerSelfDescriptionCreation()).MustHaveHappenedOnceExactly(); + result.Should().BeOfType(); + } } diff --git a/tests/administration/Administration.Service.Tests/Controllers/ConnectorsControllerTests.cs b/tests/administration/Administration.Service.Tests/Controllers/ConnectorsControllerTests.cs index b66fdbc918..85937ac239 100644 --- a/tests/administration/Administration.Service.Tests/Controllers/ConnectorsControllerTests.cs +++ b/tests/administration/Administration.Service.Tests/Controllers/ConnectorsControllerTests.cs @@ -241,4 +241,30 @@ public async Task GetConnectorOfferSubscriptionData_ReturnsExpectedResult() result.Should().HaveSameCount(offerSubscriptionData) .And.ContainInOrder(offerSubscriptionData); } + + [Fact] + public async Task GetCompaniesWithMissingSdDocument() + { + // Arrange + var paginationResponse = new Pagination.Response(new Pagination.Metadata(15, 1, 1, 15), _fixture.CreateMany(5)); + A.CallTo(() => _logic.GetConnectorsWithMissingSdDocument(A._, A._)) + .Returns(paginationResponse); + + //Act + var result = await _controller.GetConnectorsWithMissingSdDocument(); + + //Assert + result.Content.Should().HaveCount(5); + } + + [Fact] + public async Task TriggerSelfDescriptionProcess_CallsExpected() + { + // Act + var result = await _controller.TriggerSelfDescriptionProcess(); + + // Assert + A.CallTo(() => _logic.TriggerSelfDescriptionCreation()).MustHaveHappenedOnceExactly(); + result.Should().BeOfType(); + } } diff --git a/tests/administration/Administration.Service.Tests/Controllers/RegistrationControllerTest.cs b/tests/administration/Administration.Service.Tests/Controllers/RegistrationControllerTest.cs index b3104df0a4..2b5035c287 100644 --- a/tests/administration/Administration.Service.Tests/Controllers/RegistrationControllerTest.cs +++ b/tests/administration/Administration.Service.Tests/Controllers/RegistrationControllerTest.cs @@ -35,7 +35,6 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Tests.Contr public class RegistrationControllerTest { private static readonly string AccessToken = "THISISTHEACCESSTOKEN"; - private readonly IIdentityData _identity; private readonly IRegistrationBusinessLogic _logic; private readonly RegistrationController _controller; private readonly IFixture _fixture; @@ -45,13 +44,13 @@ public RegistrationControllerTest() _fixture = new Fixture().Customize(new AutoFakeItEasyCustomization { ConfigureMembers = true }); _fixture.ConfigureFixture(); - _identity = A.Fake(); - A.CallTo(() => _identity.IdentityId).Returns(Guid.NewGuid()); - A.CallTo(() => _identity.IdentityTypeId).Returns(IdentityTypeId.COMPANY_USER); - A.CallTo(() => _identity.CompanyId).Returns(Guid.NewGuid()); + var identity = A.Fake(); + A.CallTo(() => identity.IdentityId).Returns(Guid.NewGuid()); + A.CallTo(() => identity.IdentityTypeId).Returns(IdentityTypeId.COMPANY_USER); + A.CallTo(() => identity.CompanyId).Returns(Guid.NewGuid()); _logic = A.Fake(); _controller = new RegistrationController(_logic); - _controller.AddControllerContextWithClaimAndBearer(AccessToken, _identity); + _controller.AddControllerContextWithClaimAndBearer(AccessToken, identity); } [Fact] diff --git a/tests/externalsystems/SdFactory.Library.Tests/SdFactoryBusinessLogicTests.cs b/tests/externalsystems/SdFactory.Library.Tests/SdFactoryBusinessLogicTests.cs index d94eea4a3f..1dd59efca0 100644 --- a/tests/externalsystems/SdFactory.Library.Tests/SdFactoryBusinessLogicTests.cs +++ b/tests/externalsystems/SdFactory.Library.Tests/SdFactoryBusinessLogicTests.cs @@ -414,6 +414,84 @@ public async Task ProcessFinishSelfDescriptionLpForConnector_FailedWithoutMessag #endregion + #region ProcessFinishSelfDescriptionLpForCompany + + [Fact] + public async Task ProcessFinishSelfDescriptionLpForCompany_ConfirmWithValidData_CompanyIsUpdated() + { + // Arrange + var documentId = Guid.NewGuid(); + var company = new Company(Guid.NewGuid(), "con-air", CompanyStatusId.ACTIVE, DateTimeOffset.UtcNow); + A.CallTo(() => _companyRepository.AttachAndModifyCompany(A._, null, A>._)) + .Invokes((Guid _, Action? _, Action modify) => + { + modify(company); + }); + A.CallTo(() => + _documentRepository.CreateDocument(A._, A._, A._, A._, A._, A?>._)) + .Invokes((string documentName, byte[] documentContent, byte[] hash, MediaTypeId mediaTypeId, DocumentTypeId documentTypeId, Action? setupOptionalFields) => + { + var document = new Document(documentId, documentContent, hash, documentName, mediaTypeId, DateTimeOffset.UtcNow, DocumentStatusId.PENDING, documentTypeId); + setupOptionalFields?.Invoke(document); + _documents.Add(document); + }) + .Returns(new Document(documentId, null!, null!, null!, default, default, default, default)); + + const string contentJson = "{\"@context\":[\"https://www.w3.org/2018/credentials/v1\",\"https://github.com/catenax-ng/tx-sd-factory/raw/clearing-house/src/main/resources/verifiablecredentials.jsonld/sd-document-v22.10.jsonld\",\"https://w3id.org/vc/status-list/2021/v1\"],\"type\":[\"VerifiableCredential\",\"LegalPerson\"],\"issuer\":\"did:sov:12345\",\"issuanceDate\":\"2023-02-18T23:03:16Z\",\"expirationDate\":\"2023-05-19T23:03:16Z\",\"credentialSubject\":{\"bpn\":\"BPNL000000000000\",\"registrationNumber\":[{\"type\":\"local\",\"value\":\"o12345678\"}],\"headquarterAddress\":{\"countryCode\":\"DE\"},\"type\":\"LegalPerson\",\"legalAddress\":{\"countryCode\":\"DE\"},\"id\":\"did:sov:12345\"},\"credentialStatus\":{\"id\":\"https://managed-identity-wallets.int.demo.catena-x.net/api/credentials/status/123\",\"type\":\"StatusList2021Entry\",\"statusPurpose\":\"revocation\",\"statusListIndex\":\"58\",\"statusListCredential\":\"https://managed-identity-wallets.int.demo.catena-x.net/api/credentials/status/123\"},\"proof\":{\"type\":\"Ed25519Signature2018\",\"created\":\"2023-02-18T23:03:18Z\",\"proofPurpose\":\"assertionMethod\",\"verificationMethod\":\"did:sov:12345#key-1\",\"jws\":\"test\"}}"; + var data = new SelfDescriptionResponseData(company.Id, SelfDescriptionStatus.Confirm, null, contentJson); + + // Act + await _sut.ProcessFinishSelfDescriptionLpForCompany(data, CancellationToken.None); + + // Assert + A.CallTo(() => _documentRepository.CreateDocument("SelfDescription_LegalPerson.json", A._, A._, A._, DocumentTypeId.SELF_DESCRIPTION, A?>._)).MustHaveHappenedOnceExactly(); + + _documents.Should().HaveCount(1); + var document = _documents.Single(); + A.CallTo(() => _companyRepository.AttachAndModifyCompany(company.Id, null, A>._)) + .MustHaveHappenedOnceExactly(); + document.DocumentName.Should().Be("SelfDescription_LegalPerson.json"); + company.SelfDescriptionDocumentId.Should().Be(document.Id); + } + + [Fact] + public async Task ProcessFinishSelfDescriptionLpForCompany_Decline_DoesNothing() + { + // Arrange + var documentId = Guid.NewGuid(); + var company = new Company(Guid.NewGuid(), "con-air", CompanyStatusId.ACTIVE, DateTimeOffset.UtcNow); + A.CallTo(() => _companyRepository.AttachAndModifyCompany(A._, null, A>._)) + .Invokes((Guid _, Action? _, Action modify) => + { + modify(company); + }); + A.CallTo(() => + _documentRepository.CreateDocument(A._, A._, A._, A._, A._, A?>._)) + .Invokes((string documentName, byte[] documentContent, byte[] hash, MediaTypeId mediaTypeId, DocumentTypeId documentTypeId, Action? setupOptionalFields) => + { + var document = new Document(documentId, documentContent, hash, documentName, mediaTypeId, DateTimeOffset.UtcNow, DocumentStatusId.PENDING, documentTypeId); + setupOptionalFields?.Invoke(document); + _documents.Add(document); + }) + .Returns(new Document(documentId, null!, null!, null!, default, default, default, default)); + + const string contentJson = "{\"@context\":[\"https://www.w3.org/2018/credentials/v1\",\"https://github.com/catenax-ng/tx-sd-factory/raw/clearing-house/src/main/resources/verifiablecredentials.jsonld/sd-document-v22.10.jsonld\",\"https://w3id.org/vc/status-list/2021/v1\"],\"type\":[\"VerifiableCredential\",\"LegalPerson\"],\"issuer\":\"did:sov:12345\",\"issuanceDate\":\"2023-02-18T23:03:16Z\",\"expirationDate\":\"2023-05-19T23:03:16Z\",\"credentialSubject\":{\"bpn\":\"BPNL000000000000\",\"registrationNumber\":[{\"type\":\"local\",\"value\":\"o12345678\"}],\"headquarterAddress\":{\"countryCode\":\"DE\"},\"type\":\"LegalPerson\",\"legalAddress\":{\"countryCode\":\"DE\"},\"id\":\"did:sov:12345\"},\"credentialStatus\":{\"id\":\"https://managed-identity-wallets.int.demo.catena-x.net/api/credentials/status/123\",\"type\":\"StatusList2021Entry\",\"statusPurpose\":\"revocation\",\"statusListIndex\":\"58\",\"statusListCredential\":\"https://managed-identity-wallets.int.demo.catena-x.net/api/credentials/status/123\"},\"proof\":{\"type\":\"Ed25519Signature2018\",\"created\":\"2023-02-18T23:03:18Z\",\"proofPurpose\":\"assertionMethod\",\"verificationMethod\":\"did:sov:12345#key-1\",\"jws\":\"test\"}}"; + var data = new SelfDescriptionResponseData(company.Id, SelfDescriptionStatus.Failed, null, contentJson); + + // Act + await _sut.ProcessFinishSelfDescriptionLpForCompany(data, CancellationToken.None); + + // Assert + A.CallTo(() => _documentRepository.CreateDocument(A._, A._, A._, A._, DocumentTypeId.SELF_DESCRIPTION, A?>._)) + .MustNotHaveHappened(); + _documents.Should().BeEmpty(); + A.CallTo(() => _companyRepository.AttachAndModifyCompany(company.Id, null, A>._)) + .MustNotHaveHappened(); + company.SelfDescriptionDocumentId.Should().BeNull(); + } + + #endregion + #region GetSdUniqueIdentifierValue [Theory] @@ -477,9 +555,7 @@ private void SetupForProcessFinish(Company company, ApplicationChecklistEntry ap modifyApplicationChecklistEntry.Invoke(applicationChecklistEntry); }); var documentId = Guid.NewGuid(); - A.CallTo(() => - _documentRepository.CreateDocument(A._, A._, A._, A._, A._, - A?>._)) + A.CallTo(() => _documentRepository.CreateDocument(A._, A._, A._, A._, A._, A?>._)) .Invokes((string documentName, byte[] documentContent, byte[] hash, MediaTypeId mediaTypeId, DocumentTypeId documentTypeId, Action? setupOptionalFields) => { var document = new Document(documentId, documentContent, hash, documentName, mediaTypeId, DateTimeOffset.UtcNow, DocumentStatusId.PENDING, documentTypeId); diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/CompanyRepositoryTests.cs b/tests/portalbackend/PortalBackend.DBAccess.Tests/CompanyRepositoryTests.cs index 7dcc7df00e..58321446fa 100644 --- a/tests/portalbackend/PortalBackend.DBAccess.Tests/CompanyRepositoryTests.cs +++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/CompanyRepositoryTests.cs @@ -1025,6 +1025,80 @@ public async Task RemoveProviderCompanyDetails_ExecutesExpected() #endregion + #region GetCompaniesWithMissingSdDocument + + [Fact] + public async Task GetCompaniesWithMissingSdDocument_ReturnsExpectedCompanies() + { + // Arrange + var (sut, _) = await CreateSut(); + + // Act + var result = await Pagination.CreateResponseAsync( + 0, + 10, + 15, + sut.GetCompaniesWithMissingSdDocument()); + + // Assert + result.Should().NotBeNull(); + result.Content.Should().HaveCount(2).And.Satisfy( + x => x.Name == "CX-Test-Access", + x => x.Name == "Bayerische Motorenwerke AG"); + } + + #endregion + + #region GetCompaniesWithMissingSelfDescription + + [Fact] + public async Task GetCompaniesWithMissingSelfDescription_ReturnsExpectedCompanies() + { + // Arrange + var (sut, _) = await CreateSut(); + + // Act + var result = await sut.GetCompaniesWithMissingSelfDescription().ToListAsync(); + + // Assert + result.Should().NotBeNull(); + result.Should().HaveCount(2).And.Satisfy( + x => x.BusinessPartnerNumber == "BPNL00000003CRHL", + x => x.BusinessPartnerNumber == "BPNL00000003AYRE"); + } + + #endregion + + #region IsExistingCompany + + [Fact] + public async Task IsExistingCompany_WithExistingCompany_ReturnsTrue() + { + // Arrange + var (sut, _) = await CreateSut(); + + // Act + var result = await sut.IsExistingCompany(_validCompanyId).ConfigureAwait(ConfigureAwaitOptions.None); + + // Assert + result.Should().BeTrue(); + } + + [Fact] + public async Task IsExistingCompany_WithNotExistingCompany_ReturnsFalse() + { + // Arrange + var (sut, _) = await CreateSut(); + + // Act + var result = await sut.IsExistingCompany(Guid.NewGuid()).ConfigureAwait(ConfigureAwaitOptions.None); + + // Assert + result.Should().BeFalse(); + } + + #endregion + #region Setup private async Task<(ICompanyRepository, PortalDbContext)> CreateSut() diff --git a/tests/portalbackend/PortalBackend.DBAccess.Tests/ConnectorRepositoryTests.cs b/tests/portalbackend/PortalBackend.DBAccess.Tests/ConnectorRepositoryTests.cs index d9f1a8561a..eada5b3ba3 100644 --- a/tests/portalbackend/PortalBackend.DBAccess.Tests/ConnectorRepositoryTests.cs +++ b/tests/portalbackend/PortalBackend.DBAccess.Tests/ConnectorRepositoryTests.cs @@ -550,6 +550,54 @@ public async Task DeleteConnectorAssignedSubscriptions_ExecutesExpected() #endregion + #region GetConnectorsWithMissingSdDocument + + [Fact] + public async Task GetConnectorsWithMissingSdDocument_ReturnsExpectedConnectors() + { + // Arrange + var (sut, _) = await CreateSut(); + + // Act + var result = await Pagination.CreateResponseAsync( + 0, + 10, + 15, + sut.GetConnectorsWithMissingSdDocument()); + + // Assert + result.Should().NotBeNull(); + result.Content.Should().HaveCount(4).And.Satisfy( + x => x.Name == "Test Connector 7", + x => x.Name == "Test Connector 6", + x => x.Name == "Test Connector 5", + x => x.Name == "Test Connector 4"); + } + + #endregion + + #region GetConnectorsWithMissingSelfDescription + + [Fact] + public async Task GetConnectorsWithMissingSelfDescription_ReturnsExpectedConnectors() + { + // Arrange + var (sut, _) = await CreateSut(); + + // Act + var result = await sut.GetConnectorsWithMissingSelfDescription().ToListAsync().ConfigureAwait(false); + + // Assert + result.Should().NotBeNull(); + result.Should().HaveCount(4).And.Satisfy( + x => x.BusinessPartnerNumber == "BPNL00000003AYRE", + x => x.BusinessPartnerNumber == "BPNL00000003AYRE", + x => x.BusinessPartnerNumber == "BPNL00000003LLHA", + x => x.BusinessPartnerNumber == "BPNL00000003CRHK"); + } + + #endregion + private async Task<(ConnectorsRepository, PortalDbContext)> CreateSut() { var context = await _dbTestDbFixture.GetPortalDbContext(); diff --git a/tests/processes/SelfDescriptionCreation.Executor.Tests/SdCreationProcessTypeExecutorTests.cs b/tests/processes/SelfDescriptionCreation.Executor.Tests/SdCreationProcessTypeExecutorTests.cs new file mode 100644 index 0000000000..677e137548 --- /dev/null +++ b/tests/processes/SelfDescriptionCreation.Executor.Tests/SdCreationProcessTypeExecutorTests.cs @@ -0,0 +1,335 @@ +/******************************************************************************** + * Copyright (c) 2024 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 Microsoft.Extensions.Options; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Encryption; +using Org.Eclipse.TractusX.Portal.Backend.Framework.Tests.Shared; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities; +using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums; +using Org.Eclipse.TractusX.Portal.Backend.Processes.SelfDescriptionCreation.Executor.DependencyInjection; +using Org.Eclipse.TractusX.Portal.Backend.SdFactory.Library; +using System.Security.Cryptography; +using System.Text.Json; + +namespace Org.Eclipse.TractusX.Portal.Backend.Processes.SelfDescriptionCreation.Executor.Tests; + +public class SdCreationProcessTypeExecutorTests +{ + private readonly ICompanyRepository _companyRepository; + private readonly IConnectorsRepository _connectorsRepository; + private readonly SdCreationProcessTypeExecutor _executor; + private readonly IFixture _fixture; + private readonly IEnumerable _executableSteps; + private readonly ISdFactoryService _sdFactoryService; + + public SdCreationProcessTypeExecutorTests() + { + _fixture = new Fixture().Customize(new AutoFakeItEasyCustomization { ConfigureMembers = true }); + _fixture.Behaviors.OfType().ToList() + .ForEach(b => _fixture.Behaviors.Remove(b)); + _fixture.Behaviors.Add(new OmitOnRecursionBehavior()); + + _sdFactoryService = A.Fake(); + var portalRepositories = A.Fake(); + _companyRepository = A.Fake(); + _connectorsRepository = A.Fake(); + + A.CallTo(() => portalRepositories.GetInstance()) + .Returns(_connectorsRepository); + A.CallTo(() => portalRepositories.GetInstance()) + .Returns(_companyRepository); + + var settings = new SelfDescriptionProcessSettings + { + SelfDescriptionDocumentUrl = "https://selfdescription.url" + }; + + _executor = new SdCreationProcessTypeExecutor(portalRepositories, _sdFactoryService, Options.Create(settings)); + + _executableSteps = new[] { ProcessStepTypeId.SELF_DESCRIPTION_COMPANY_CREATION, ProcessStepTypeId.SELF_DESCRIPTION_CONNECTOR_CREATION }; + } + + #region InitializeProcess + + [Fact] + public async Task InitializeProcess_WithExisting_ReturnsExpected() + { + // Arrange + var processId = Guid.NewGuid(); + + // Act + var result = await _executor.InitializeProcess(processId, _fixture.CreateMany()); + + // Assert + result.Should().NotBeNull(); + result.Modified.Should().BeFalse(); + result.ScheduleStepTypeIds.Should().BeNull(); + } + + #endregion + + #region ExecuteProcessStep + + [Fact] + public async Task ExecuteProcessStep_ForCompanies_ReturnsExpected() + { + // Act initialize + var processId = Guid.NewGuid(); + var initializationResult = await _executor.InitializeProcess(processId, _fixture.CreateMany()); + + // Assert initialize + initializationResult.Should().NotBeNull(); + initializationResult.Modified.Should().BeFalse(); + initializationResult.ScheduleStepTypeIds.Should().BeNull(); + + // Arrange + var company1 = new ValueTuple, string?, string>( + Guid.NewGuid(), + new List<(UniqueIdentifierId Id, string Value)> { new(UniqueIdentifierId.VAT_ID, "test") }, + "BPNL000000001TEST", + "DE"); + var company2 = new ValueTuple, string?, string>( + Guid.NewGuid(), + new List<(UniqueIdentifierId Id, string Value)> { new(UniqueIdentifierId.VAT_ID, "test") }, + "BPNL000000002TEST", + "DE"); + var companies = + new List<(Guid Id, IEnumerable<(UniqueIdentifierId Id, string Value)> UniqueIdentifiers, string? + BusinessPartnerNumber, string CountryCode)> + { + company1, + company2 + }; + A.CallTo(() => _companyRepository.GetCompaniesWithMissingSelfDescription()) + .Returns(companies.ToAsyncEnumerable()); + + // Act + var result = await _executor.ExecuteProcessStep(ProcessStepTypeId.SELF_DESCRIPTION_COMPANY_CREATION, Enumerable.Empty(), CancellationToken.None); + + // Assert + result.Modified.Should().BeTrue(); + result.ScheduleStepTypeIds.Should().ContainSingle(x => x == ProcessStepTypeId.SELF_DESCRIPTION_COMPANY_CREATION); + result.ProcessStepStatusId.Should().Be(ProcessStepStatusId.DONE); + + A.CallTo(() => _sdFactoryService.RegisterSelfDescriptionAsync(company1.Item1, A>._, A._, A._, A._)) + .MustHaveHappenedOnceExactly(); + } + + [Fact] + public async Task ExecuteProcessStep_ForConnectors_ReturnsExpected() + { + // Act initialize + var processId = Guid.NewGuid(); + var initializationResult = await _executor.InitializeProcess(processId, _fixture.CreateMany()); + + // Assert initialize + initializationResult.Should().NotBeNull(); + initializationResult.Modified.Should().BeFalse(); + initializationResult.ScheduleStepTypeIds.Should().BeNull(); + + // Arrange + var connector1 = new ValueTuple( + Guid.NewGuid(), + "BPNL000000001TEST", + Guid.NewGuid()); + var connector2 = new ValueTuple( + Guid.NewGuid(), + "BPNL000000002TEST", + Guid.NewGuid()); + var connectors = new List<(Guid Id, string? BusinessPartnerNumber, Guid? SelfDescriptionDocumentId)> + { + connector1, + connector2 + }; + A.CallTo(() => _connectorsRepository.GetConnectorsWithMissingSelfDescription()) + .Returns(connectors.ToAsyncEnumerable()); + + // Act + var result = await _executor.ExecuteProcessStep(ProcessStepTypeId.SELF_DESCRIPTION_CONNECTOR_CREATION, Enumerable.Empty(), CancellationToken.None); + + // Assert + result.Modified.Should().BeTrue(); + result.ScheduleStepTypeIds.Should().ContainSingle(x => x == ProcessStepTypeId.SELF_DESCRIPTION_CONNECTOR_CREATION); + result.ProcessStepStatusId.Should().Be(ProcessStepStatusId.DONE); + + A.CallTo(() => _sdFactoryService.RegisterConnectorAsync(connector1.Item1, A._, "BPNL000000001TEST", A._)) + .MustHaveHappenedOnceExactly(); + } + + [Fact] + public async Task ExecuteProcessStep_ThrowingTestException_ReturnsExpected() + { + // Arrange initialize + var processId = Guid.NewGuid(); + + // Act initialize + var initializationResult = await _executor.InitializeProcess(processId, _fixture.CreateMany()); + + // Assert initialize + initializationResult.Should().NotBeNull(); + initializationResult.Modified.Should().BeFalse(); + initializationResult.ScheduleStepTypeIds.Should().BeNull(); + + // Arrange execute + var company1 = new ValueTuple, string?, string>( + Guid.NewGuid(), + new List<(UniqueIdentifierId Id, string Value)> { new(UniqueIdentifierId.VAT_ID, "test") }, + "BPNL000000001TEST", + "DE"); + var company2 = new ValueTuple, string?, string>( + Guid.NewGuid(), + new List<(UniqueIdentifierId Id, string Value)> { new(UniqueIdentifierId.VAT_ID, "test") }, + "BPNL000000002TEST", + "DE"); + var companies = + new List<(Guid Id, IEnumerable<(UniqueIdentifierId Id, string Value)> UniqueIdentifiers, string? + BusinessPartnerNumber, string CountryCode)> + { + company1, + company2 + }; + A.CallTo(() => _companyRepository.GetCompaniesWithMissingSelfDescription()) + .Returns(companies.ToAsyncEnumerable()); + + var error = _fixture.Create(); + A.CallTo(() => _sdFactoryService.RegisterSelfDescriptionAsync(A._, A>._, A._, A._, A._)) + .Throws(error); + + // Act execute + var executionResult = await _executor.ExecuteProcessStep(ProcessStepTypeId.SELF_DESCRIPTION_COMPANY_CREATION, Enumerable.Empty(), CancellationToken.None); + + // Assert execute + executionResult.Modified.Should().BeTrue(); + executionResult.ProcessStepStatusId.Should().Be(ProcessStepStatusId.FAILED); + executionResult.ScheduleStepTypeIds.Should().ContainInOrder(ProcessStepTypeId.RETRIGGER_SELF_DESCRIPTION_COMPANY_CREATION); + executionResult.SkipStepTypeIds.Should().BeNull(); + executionResult.ProcessMessage.Should().Be(error.Message); + } + + [Fact] + public async Task ExecuteProcessStep_ThrowingSystemException_Throws() + { + // Arrange initialize + var processId = Guid.NewGuid(); + + // Act initialize + var initializationResult = await _executor.InitializeProcess(processId, _fixture.CreateMany()); + + // Assert initialize + initializationResult.Should().NotBeNull(); + initializationResult.Modified.Should().BeFalse(); + initializationResult.ScheduleStepTypeIds.Should().BeNull(); + + // Arrange execute + var company1 = new ValueTuple, string?, string>( + Guid.NewGuid(), + new List<(UniqueIdentifierId Id, string Value)> { new(UniqueIdentifierId.VAT_ID, "test") }, + "BPNL000000001TEST", + "DE"); + var company2 = new ValueTuple, string?, string>( + Guid.NewGuid(), + new List<(UniqueIdentifierId Id, string Value)> { new(UniqueIdentifierId.VAT_ID, "test") }, + "BPNL000000002TEST", + "DE"); + var companies = + new List<(Guid Id, IEnumerable<(UniqueIdentifierId Id, string Value)> UniqueIdentifiers, string? + BusinessPartnerNumber, string CountryCode)> + { + company1, + company2 + }; + A.CallTo(() => _companyRepository.GetCompaniesWithMissingSelfDescription()) + .Returns(companies.ToAsyncEnumerable()); + + var error = new SystemException(_fixture.Create()); + A.CallTo(() => _sdFactoryService.RegisterSelfDescriptionAsync(A._, A>._, A._, A._, A._)) + .Throws(error); + + // Act execute + async Task Act() => await _executor.ExecuteProcessStep(ProcessStepTypeId.SELF_DESCRIPTION_COMPANY_CREATION, Enumerable.Empty(), CancellationToken.None); + var ex = await Assert.ThrowsAsync(Act); + + // Assert execute + ex.Message.Should().Be(error.Message); + } + + #endregion + + #region GetProcessTypeId + + [Fact] + public void GetProcessTypeId_ReturnsExpected() + { + // Act + var result = _executor.GetProcessTypeId(); + + // Assert + result.Should().Be(ProcessTypeId.SELF_DESCRIPTION_CREATION); + } + + #endregion + + #region IsExecutableStepTypeId + + [Theory] + [InlineData(ProcessStepTypeId.SELF_DESCRIPTION_COMPANY_CREATION, true)] + [InlineData(ProcessStepTypeId.SELF_DESCRIPTION_CONNECTOR_CREATION, true)] + [InlineData(ProcessStepTypeId.START_AUTOSETUP, false)] + public void IsExecutableProcessStep_ReturnsExpected(ProcessStepTypeId processStepTypeId, bool expectedValue) + { + // Act + var result = _executor.IsExecutableStepTypeId(processStepTypeId); + + // Assert + result.Should().Be(expectedValue); + } + + #endregion + + #region IsLockRequested + + [Fact] + public async Task IsLockRequested_ReturnsExpected() + { + // Act + var result = await _executor.IsLockRequested(ProcessStepTypeId.SELF_DESCRIPTION_COMPANY_CREATION); + + // Assert + result.Should().Be(false); + } + + #endregion + + #region GetExecutableStepTypeIds + + [Fact] + public void GetExecutableStepTypeIds_ReturnsExpected() + { + //Act + var result = _executor.GetExecutableStepTypeIds(); + + // Assert + result.Should().HaveCount(_executableSteps.Count()) + .And.BeEquivalentTo(_executableSteps); + } + + #endregion +} diff --git a/tests/processes/SelfDescriptionCreation.Executor.Tests/SelfDescriptionCreation.Executor.Tests.csproj b/tests/processes/SelfDescriptionCreation.Executor.Tests/SelfDescriptionCreation.Executor.Tests.csproj new file mode 100644 index 0000000000..33af9370c6 --- /dev/null +++ b/tests/processes/SelfDescriptionCreation.Executor.Tests/SelfDescriptionCreation.Executor.Tests.csproj @@ -0,0 +1,50 @@ + + + + + net8.0 + enable + enable + false + Org.Eclipse.TractusX.Portal.Backend.Processes.SelfDescriptionCreation.Executor.Tests + Org.Eclipse.TractusX.Portal.Backend.Processes.SelfDescriptionCreation.Executor.Tests + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/tests/processes/SelfDescriptionCreation.Executor.Tests/Usings.cs b/tests/processes/SelfDescriptionCreation.Executor.Tests/Usings.cs new file mode 100644 index 0000000000..14669b9c8a --- /dev/null +++ b/tests/processes/SelfDescriptionCreation.Executor.Tests/Usings.cs @@ -0,0 +1,24 @@ +/******************************************************************************** + * Copyright (c) 2024 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 + ********************************************************************************/ + +global using AutoFixture; +global using AutoFixture.AutoFakeItEasy; +global using FakeItEasy; +global using FluentAssertions; +global using Xunit;