diff --git a/CHANGELOG.md b/CHANGELOG.md
index 52c25d100b..7d24faf1cc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,22 @@
New features, fixed bugs, known defects and other noteworthy changes to each release of the Catena-X Portal Backend.
+## 2.2.0-RC2
+
+### Change
+
+* **Network Registration (Administration Service)**
+ * enhanced endpoint `GET /api/administration/registration/network/companies` with additional fields and filter possibilities [#916](https://github.com/eclipse-tractusx/portal-backend/pull/916)
+
+### Bugfixes
+
+* **Application Activation**
+ * adjusted the set of the theme only for shared idps [#852](https://github.com/eclipse-tractusx/portal-backend/pull/852)
+* **App Roles**
+ * added a duplication check for roles before adding them [#877](https://github.com/eclipse-tractusx/portal-backend/pull/877)
+* **BPDM**
+ * adjusted the structure of the bpdm request for the `input/business-partners` request [#928](https://github.com/eclipse-tractusx/portal-backend/pull/928)
+
## 2.2.0-RC1
### Change
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index e79c6b364f..0a1bbb7255 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -20,6 +20,6 @@
2.2.0
- RC1
+ RC2
diff --git a/src/administration/Administration.Service/BusinessLogic/IRegistrationBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/IRegistrationBusinessLogic.cs
index 1ce740c945..41b1581324 100644
--- a/src/administration/Administration.Service/BusinessLogic/IRegistrationBusinessLogic.cs
+++ b/src/administration/Administration.Service/BusinessLogic/IRegistrationBusinessLogic.cs
@@ -32,7 +32,7 @@ public interface IRegistrationBusinessLogic
{
Task GetCompanyWithAddressAsync(Guid applicationId);
Task> GetCompanyApplicationDetailsAsync(int page, int size, CompanyApplicationStatusFilter? companyApplicationStatusFilter, string? companyName);
- Task> GetOspCompanyDetailsAsync(int page, int size, CompanyApplicationStatusFilter? companyApplicationStatusFilter, string? companyName);
+ Task> GetOspCompanyDetailsAsync(int page, int size, CompanyApplicationStatusFilter? companyApplicationStatusFilter, string? companyName, string? externalId, DateCreatedOrderFilter? dateCreatedOrderFilter);
Task> GetAllCompanyApplicationsDetailsAsync(int page, int size, string? companyName);
Task UpdateCompanyBpn(Guid applicationId, string bpn);
diff --git a/src/administration/Administration.Service/BusinessLogic/RegistrationBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/RegistrationBusinessLogic.cs
index 9b1b59e811..8d78e3abb0 100644
--- a/src/administration/Administration.Service/BusinessLogic/RegistrationBusinessLogic.cs
+++ b/src/administration/Administration.Service/BusinessLogic/RegistrationBusinessLogic.cs
@@ -161,33 +161,37 @@ private async Task GetCompanyWithAddressAsyncInternal(Gu
.AsAsyncEnumerable()));
}
- public Task> GetOspCompanyDetailsAsync(int page, int size, CompanyApplicationStatusFilter? companyApplicationStatusFilter, string? companyName)
+ public Task> GetOspCompanyDetailsAsync(int page, int size, CompanyApplicationStatusFilter? companyApplicationStatusFilter, string? companyName, string? externalId, DateCreatedOrderFilter? dateCreatedOrderFilter)
{
if (companyName != null && !companyName.IsValidCompanyName())
{
throw ControllerArgumentException.Create(ValidationExpressionErrors.INCORRECT_COMPANY_NAME, [new("name", "CompanyName")]);
}
- var applications = portalRepositories.GetInstance()
+ var applicationsQuery = portalRepositories.GetInstance()
.GetExternalCompanyApplicationsFilteredQuery(_identityData.CompanyId,
- companyName?.Length >= 3 ? companyName : null,
+ companyName?.Length >= 3 ? companyName : null, externalId,
GetCompanyApplicationStatusIds(companyApplicationStatusFilter));
+ var orderedQuery = dateCreatedOrderFilter == null || dateCreatedOrderFilter.Value == DateCreatedOrderFilter.DESC
+ ? applicationsQuery.AsSplitQuery().OrderByDescending(application => application.DateCreated)
+ : applicationsQuery.AsSplitQuery().OrderBy(application => application.DateCreated);
+
return Pagination.CreateResponseAsync(
page,
size,
_settings.ApplicationsMaxPageSize,
(skip, take) => new Pagination.AsyncSource(
- applications.CountAsync(),
- applications
- .AsSplitQuery()
- .OrderByDescending(application => application.DateCreated)
+ applicationsQuery.CountAsync(),
+ orderedQuery
.Skip(skip)
.Take(take)
.Select(application => new CompanyDetailsOspOnboarding(
application.CompanyId,
+ application.NetworkRegistration!.ExternalId,
application.Id,
application.ApplicationStatusId,
application.DateCreated,
+ application.Company!.DateCreated,
application.DateLastChanged,
application.Company!.Name,
application.Company.CompanyAssignedRoles.Select(companyAssignedRoles => companyAssignedRoles.CompanyRoleId),
@@ -210,7 +214,7 @@ private async Task GetCompanyWithAddressAsyncInternal(Gu
_settings.ApplicationsMaxPageSize,
(skip, take) => new Pagination.AsyncSource(
applications.CountAsync(),
- applications.OrderByDescending(application => application.DateCreated)
+ applications.OrderByDescending(application => application.Company!.DateCreated)
.Skip(skip)
.Take(take)
.Select(application => new
@@ -394,7 +398,7 @@ public Task TriggerChecklistAsync(Guid applicationId, ApplicationChecklistEntryT
throw new ControllerArgumentException($"The processStep {processStepTypeId} is not retriggerable");
}
- var nextStepData = processStepTypeId.GetNextProcessStepDataForManualTriggerProcessStepId(_settings.ClearinghouseConnectDisabled);
+ var nextStepData = processStepTypeId.GetNextProcessStepDataForManualTriggerProcessStepId();
if (nextStepData == default)
{
throw new UnexpectedConditionException($"While the processStep {processStepTypeId} is configured to be retriggerable there is no next step configured");
diff --git a/src/administration/Administration.Service/BusinessLogic/RegistrationSettings.cs b/src/administration/Administration.Service/BusinessLogic/RegistrationSettings.cs
index 2ab34cac97..ffa234b85e 100644
--- a/src/administration/Administration.Service/BusinessLogic/RegistrationSettings.cs
+++ b/src/administration/Administration.Service/BusinessLogic/RegistrationSettings.cs
@@ -40,11 +40,6 @@ public class RegistrationSettings
public string HelpAddress { get; set; } = null!;
public bool UseDimWallet { get; set; }
-
- ///
- /// If true all sd factory calls are disabled and won't be called. The respective process steps will be skipped.
- ///
- public bool ClearinghouseConnectDisabled { get; set; }
}
public static class RegistrationSettingsExtension
diff --git a/src/administration/Administration.Service/BusinessLogic/UserRolesBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/UserRolesBusinessLogic.cs
index 783ee597be..ab620c7008 100644
--- a/src/administration/Administration.Service/BusinessLogic/UserRolesBusinessLogic.cs
+++ b/src/administration/Administration.Service/BusinessLogic/UserRolesBusinessLogic.cs
@@ -154,7 +154,7 @@ private async Task> ModifyUserRolesInternal(
var distinctRoles = roles.Where(role => !string.IsNullOrWhiteSpace(role)).Distinct().ToImmutableList();
var existingRoles = await getUserRoleModificationData(companyUserId, distinctRoles, offerId).ToListAsync().ConfigureAwait(false);
existingRoles.DuplicatesBy(x => x.CompanyUserRoleText).IfAny(
- duplicateRoles => throw new ConflictException($"roles {string.Join(",", $"{duplicateRoles.Select(role => $"[{role.CompanyUserRoleText}, {role.CompanyUserRoleId}]")}")} are ambigous"));
+ duplicateRoles => throw new ConflictException($"roles {string.Join(",", duplicateRoles.Select(role => $"[{role.CompanyUserRoleText}, {role.CompanyUserRoleId}]"))} are ambigous"));
distinctRoles.Except(existingRoles.Where(r => r.IsAssignable).Select(r => r.CompanyUserRoleText)).IfAny(
nonExistingRoles => throw new ControllerArgumentException($"Invalid roles {string.Join(",", nonExistingRoles)}", nameof(roles)));
diff --git a/src/administration/Administration.Service/Controllers/RegistrationController.cs b/src/administration/Administration.Service/Controllers/RegistrationController.cs
index 6dfd31b77a..c84b2fd643 100644
--- a/src/administration/Administration.Service/Controllers/RegistrationController.cs
+++ b/src/administration/Administration.Service/Controllers/RegistrationController.cs
@@ -568,6 +568,8 @@ public async Task RetriggerDeleteCentralUser([FromRoute] Guid p
/// size to get number of records
/// Search by company applicationstatus
/// search by company name
+ /// search by external Id
+ /// sort result by dateCreated ascending or descending
/// OSp Company Application Details
///
/// Example: GET: api/administration/registration/network/companies?companyName=Car&page=0&size=4&companyApplicationStatus=Closed
@@ -579,6 +581,7 @@ public async Task RetriggerDeleteCentralUser([FromRoute] Guid p
[Authorize(Policy = PolicyTypes.ValidCompany)]
[Route("network/companies")]
[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);
+ public Task> GetOspCompanyDetailsAsync([FromQuery] int page, [FromQuery] int size, [FromQuery] CompanyApplicationStatusFilter? companyApplicationStatusFilter = null, [FromQuery] string? companyName = null, [FromQuery] string? externalId = null, [FromQuery] DateCreatedOrderFilter? dateCreatedOrderFilter = null) =>
+ _logic.GetOspCompanyDetailsAsync(page, size, companyApplicationStatusFilter, companyName, externalId, dateCreatedOrderFilter);
}
+
diff --git a/src/portalbackend/PortalBackend.PortalEntities/Enums/CompanyApplicationStatusFilter.cs b/src/administration/Administration.Service/Models/CompanyApplicationStatusFilter.cs
similarity index 93%
rename from src/portalbackend/PortalBackend.PortalEntities/Enums/CompanyApplicationStatusFilter.cs
rename to src/administration/Administration.Service/Models/CompanyApplicationStatusFilter.cs
index 19f71d7284..9e8bac9a38 100644
--- a/src/portalbackend/PortalBackend.PortalEntities/Enums/CompanyApplicationStatusFilter.cs
+++ b/src/administration/Administration.Service/Models/CompanyApplicationStatusFilter.cs
@@ -17,7 +17,7 @@
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/
-namespace Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums;
+namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models;
///
/// Filter operations for the CompanyApplicationStatus
diff --git a/src/administration/Administration.Service/Models/CompanyDetailsOspOnboarding.cs b/src/administration/Administration.Service/Models/CompanyDetailsOspOnboarding.cs
index d6088add81..f51f9c1e32 100644
--- a/src/administration/Administration.Service/Models/CompanyDetailsOspOnboarding.cs
+++ b/src/administration/Administration.Service/Models/CompanyDetailsOspOnboarding.cs
@@ -25,9 +25,11 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.Models;
public record CompanyDetailsOspOnboarding(
[property: JsonPropertyName("companyId")] Guid CompanyId,
+ [property: JsonPropertyName("externalId")] string? ExternalId,
[property: JsonPropertyName("applicationId")] Guid ApplicationId,
[property: JsonPropertyName("applicationStatus")] CompanyApplicationStatusId CompanyApplicationStatusId,
- [property: JsonPropertyName("applicationDateCreated")] DateTimeOffset DateCreated,
+ [property: JsonPropertyName("applicationDateCreated")] DateTimeOffset ApplicationDateCreated,
+ [property: JsonPropertyName("dateCreated")] DateTimeOffset DateCreated,
[property: JsonPropertyName("lastChangedDate")] DateTimeOffset? DateLastChanged,
[property: JsonPropertyName("companyName")] string CompanyName,
[property: JsonPropertyName("companyRoles")] IEnumerable CompanyRoles,
diff --git a/src/administration/Administration.Service/Models/DateCreatedOrderFilter.cs b/src/administration/Administration.Service/Models/DateCreatedOrderFilter.cs
new file mode 100644
index 0000000000..cd6a15903d
--- /dev/null
+++ b/src/administration/Administration.Service/Models/DateCreatedOrderFilter.cs
@@ -0,0 +1,26 @@
+/********************************************************************************
+ * 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 enum DateCreatedOrderFilter
+{
+ ASC,
+ DESC
+}
diff --git a/src/administration/Administration.Service/appsettings.json b/src/administration/Administration.Service/appsettings.json
index 380e0959b4..e5736f627a 100644
--- a/src/administration/Administration.Service/appsettings.json
+++ b/src/administration/Administration.Service/appsettings.json
@@ -259,8 +259,7 @@
"Registration": {
"ApplicationsMaxPageSize": 20,
"DocumentTypeIds": [],
- "UseDimWallet": false,
- "ClearinghouseConnectDisabled": false
+ "UseDimWallet": false
},
"UserManagement": {
"ApplicationsMaxPageSize": 20,
diff --git a/src/externalsystems/Bpdm.Library/Models/BpdmLegalEntityData.cs b/src/externalsystems/Bpdm.Library/Models/BpdmLegalEntityData.cs
index 9023eae207..97d302b667 100644
--- a/src/externalsystems/Bpdm.Library/Models/BpdmLegalEntityData.cs
+++ b/src/externalsystems/Bpdm.Library/Models/BpdmLegalEntityData.cs
@@ -111,5 +111,5 @@ public record BpdmLegalEntityData(
BpdmLegalEntity LegalEntity,
BpdmSite? Site,
BpdmAddress Address,
- bool OwnCompanyData
+ bool IsOwnCompanyData
);
diff --git a/src/marketplace/Apps.Service/BusinessLogic/AppChangeBusinessLogic.cs b/src/marketplace/Apps.Service/BusinessLogic/AppChangeBusinessLogic.cs
index 03cdaf939b..760f57d7e8 100644
--- a/src/marketplace/Apps.Service/BusinessLogic/AppChangeBusinessLogic.cs
+++ b/src/marketplace/Apps.Service/BusinessLogic/AppChangeBusinessLogic.cs
@@ -111,11 +111,19 @@ private async Task> InsertActiveAppUserRoleAsync(Guid a
{
throw new ForbiddenException($"Company {_identityData.CompanyId} is not the provider company of app {appId}");
}
+ var roleData = await AppExtensions.CreateUserRolesWithDescriptions(_portalRepositories.GetInstance(), appId, userRoles);
+
+ // When user will try to upload the same role names which are already attched to an APP.
+ // so, no role will be added against the given appId so, no need to procced further
+ // No need to Add roles to client
+ // No need to update the Offer entity
+ // When nothing has happened, no need to send notifications
+ if (!roleData.Any())
+ return roleData;
- var roleData = AppExtensions.CreateUserRolesWithDescriptions(_portalRepositories.GetInstance(), appId, userRoles);
foreach (var clientId in result.ClientClientIds)
{
- await _provisioningManager.AddRolesToClientAsync(clientId, userRoles.Select(x => x.Role)).ConfigureAwait(ConfigureAwaitOptions.None);
+ await _provisioningManager.AddRolesToClientAsync(clientId, roleData.Select(x => x.RoleName)).ConfigureAwait(ConfigureAwaitOptions.None);
}
_portalRepositories.GetInstance().AttachAndModifyOffer(appId, offer =>
diff --git a/src/marketplace/Apps.Service/BusinessLogic/AppReleaseBusinessLogic.cs b/src/marketplace/Apps.Service/BusinessLogic/AppReleaseBusinessLogic.cs
index 9c6ee51664..84b2e24c4b 100644
--- a/src/marketplace/Apps.Service/BusinessLogic/AppReleaseBusinessLogic.cs
+++ b/src/marketplace/Apps.Service/BusinessLogic/AppReleaseBusinessLogic.cs
@@ -91,7 +91,13 @@ private async Task> InsertAppUserRoleAsync(Guid appId,
{
throw new ForbiddenException($"Company {companyId} is not the provider company of app {appId}");
}
- var roleData = AppExtensions.CreateUserRolesWithDescriptions(_portalRepositories.GetInstance(), appId, userRoles);
+ var roleData = await AppExtensions.CreateUserRolesWithDescriptions(_portalRepositories.GetInstance(), appId, userRoles);
+
+ // When user will try to upload the same role names which are already attched to an APP.
+ // so, no role will be added against the given appId so, no need to procced further
+ // No need to update the Offer entity
+ if (!roleData.Any())
+ return roleData;
_portalRepositories.GetInstance().AttachAndModifyOffer(appId, offer =>
offer.DateLastChanged = DateTimeOffset.UtcNow);
diff --git a/src/marketplace/Apps.Service/Extensions/AppExtensions.cs b/src/marketplace/Apps.Service/Extensions/AppExtensions.cs
index 622930827e..69ba2f2542 100644
--- a/src/marketplace/Apps.Service/Extensions/AppExtensions.cs
+++ b/src/marketplace/Apps.Service/Extensions/AppExtensions.cs
@@ -19,6 +19,7 @@
using Org.Eclipse.TractusX.Portal.Backend.Apps.Service.ViewModels;
using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling;
+using Org.Eclipse.TractusX.Portal.Backend.Framework.Linq;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Entities;
@@ -46,6 +47,7 @@ public static void ValidateAppUserRole(Guid appId, IEnumerable appU
{
throw new ControllerArgumentException("Language Code must not be empty");
}
+ appUserRolesDescription.DuplicatesBy(x => x.Role).IfAny(duplicateRoles => throw new ControllerArgumentException($"Roles are ambiguous: {string.Join(",", duplicateRoles.Select(x => x.Role))}"));
}
///
@@ -56,8 +58,10 @@ public static void ValidateAppUserRole(Guid appId, IEnumerable appU
/// id of the app to create the roles for
/// the user roles to add
/// returns the created appRoleData
- public static IEnumerable CreateUserRolesWithDescriptions(IUserRolesRepository userRolesRepository, Guid appId, IEnumerable userRoles) =>
- userRoles.Zip(
+ public static async Task> CreateUserRolesWithDescriptions(IUserRolesRepository userRolesRepository, Guid appId, IEnumerable userRoles)
+ {
+ userRoles = await GetUniqueAppUserRoles(userRolesRepository, appId, userRoles);
+ return userRoles.Zip(
userRolesRepository.CreateAppUserRoles(userRoles.Select(x => (appId, x.Role))),
(AppUserRole appUserRole, UserRole userRole) =>
{
@@ -65,4 +69,19 @@ public static IEnumerable CreateUserRolesWithDescriptions(IUserRole
return new AppRoleData(userRole.Id, appUserRole.Role);
})
.ToList();
+ }
+
+ ///
+ /// Get unique roles by eleminating the duplicate roles from the request (client) and existing roles from the Database
+ ///
+ ///
+ /// repository
+ /// id of the app
+ /// the app user roles
+ /// returns the filtered and unique roles
+ private static async Task> GetUniqueAppUserRoles(IUserRolesRepository userRolesRepository, Guid appId, IEnumerable userRoles)
+ {
+ var existingRoles = await userRolesRepository.GetUserRolesForOfferIdAsync(appId).ToListAsync().ConfigureAwait(false);
+ return userRoles.ExceptBy(existingRoles, userRole => userRole.Role);
+ }
}
diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/ApplicationRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/ApplicationRepository.cs
index a4d2f39cc2..fe7a37738a 100644
--- a/src/portalbackend/PortalBackend.DBAccess/Repositories/ApplicationRepository.cs
+++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/ApplicationRepository.cs
@@ -134,12 +134,13 @@ public IQueryable GetCompanyApplicationsFilteredQuery(string
(companyName == null || EF.Functions.ILike(application.Company!.Name, $"{companyName.EscapeForILike()}%")) &&
(applicationStatusIds == null || applicationStatusIds.Contains(application.ApplicationStatusId)));
- public IQueryable GetExternalCompanyApplicationsFilteredQuery(Guid onboardingServiceProviderId, string? companyName, IEnumerable applicationStatusIds) =>
+ public IQueryable GetExternalCompanyApplicationsFilteredQuery(Guid onboardingServiceProviderId, string? companyName, string? externalId, IEnumerable applicationStatusIds) =>
portalDbContext.CompanyApplications.AsNoTracking()
.Where(application =>
application.CompanyApplicationTypeId == CompanyApplicationTypeId.EXTERNAL &&
application.OnboardingServiceProviderId == onboardingServiceProviderId &&
(companyName == null || EF.Functions.ILike(application.Company!.Name, $"{companyName.EscapeForILike()}%")) &&
+ (externalId == null || application.NetworkRegistration!.ExternalId == externalId) &&
applicationStatusIds.Contains(application.ApplicationStatusId));
public Task GetCompanyApplicationDetailDataAsync(Guid applicationId, Guid userCompanyId, Guid? companyId) =>
@@ -205,7 +206,7 @@ public IQueryable GetExternalCompanyApplicationsFilteredQuer
.SingleOrDefaultAsync();
///
- public Task<(Guid CompanyId, string CompanyName, string? BusinessPartnerNumber, IEnumerable IamIdpAliasse, CompanyApplicationTypeId ApplicationTypeId, Guid? NetworkRegistrationProcessId)> GetCompanyAndApplicationDetailsForApprovalAsync(Guid applicationId) =>
+ public Task<(Guid CompanyId, string CompanyName, string? BusinessPartnerNumber, IEnumerable SharedIdpAliase, CompanyApplicationTypeId ApplicationTypeId, Guid? NetworkRegistrationProcessId)> GetCompanyAndApplicationDetailsForApprovalAsync(Guid applicationId) =>
portalDbContext.CompanyApplications.Where(companyApplication =>
companyApplication.Id == applicationId &&
companyApplication.ApplicationStatusId == CompanyApplicationStatusId.SUBMITTED)
@@ -213,7 +214,7 @@ public IQueryable GetExternalCompanyApplicationsFilteredQuer
ca.CompanyId,
ca.Company!.Name,
ca.Company.BusinessPartnerNumber,
- ca.Company.IdentityProviders.Select(x => x.IamIdentityProvider!.IamIdpAlias),
+ ca.Company.IdentityProviders.Where(x => x.IdentityProviderTypeId == IdentityProviderTypeId.SHARED && x.IamIdentityProvider != null).Select(x => x.IamIdentityProvider!.IamIdpAlias),
ca.CompanyApplicationTypeId,
ca.CompanyApplicationTypeId == CompanyApplicationTypeId.EXTERNAL ?
ca.Company.NetworkRegistration!.ProcessId :
diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/IApplicationRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/IApplicationRepository.cs
index 0c9bf25cdb..15d068306c 100644
--- a/src/portalbackend/PortalBackend.DBAccess/Repositories/IApplicationRepository.cs
+++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/IApplicationRepository.cs
@@ -34,11 +34,11 @@ public interface IApplicationRepository
Task<(bool Exists, bool IsUserOfCompany, CompanyApplicationStatusId ApplicationStatus)> GetOwnCompanyApplicationStatusUserDataUntrackedAsync(Guid applicationId, Guid companyId);
Task GetOwnCompanyApplicationUserEmailDataAsync(Guid applicationId, Guid companyUserId, IEnumerable submitDocumentTypeIds);
IQueryable GetCompanyApplicationsFilteredQuery(string? companyName, IEnumerable applicationStatusIds);
- IQueryable GetExternalCompanyApplicationsFilteredQuery(Guid onboardingServiceProviderId, string? companyName, IEnumerable applicationStatusIds);
+ IQueryable GetExternalCompanyApplicationsFilteredQuery(Guid onboardingServiceProviderId, string? companyName, string? externalId, IEnumerable applicationStatusIds);
Task GetCompanyApplicationDetailDataAsync(Guid applicationId, Guid userCompanyId, Guid? companyId);
Task<(string CompanyName, string? FirstName, string? LastName, string? Email, IEnumerable<(Guid ApplicationId, CompanyApplicationStatusId ApplicationStatusId, IEnumerable<(string? FirstName, string? LastName, string? Email)> InvitedUsers)> Applications)> GetCompanyApplicationsDeclineData(Guid companyUserId, IEnumerable applicationStatusIds);
Task<(bool IsValidApplicationId, Guid CompanyId, bool IsSubmitted)> GetCompanyIdSubmissionStatusForApplication(Guid applicationId);
- Task<(Guid CompanyId, string CompanyName, string? BusinessPartnerNumber, IEnumerable IamIdpAliasse, CompanyApplicationTypeId ApplicationTypeId, Guid? NetworkRegistrationProcessId)> GetCompanyAndApplicationDetailsForApprovalAsync(Guid applicationId);
+ Task<(Guid CompanyId, string CompanyName, string? BusinessPartnerNumber, IEnumerable SharedIdpAliase, CompanyApplicationTypeId ApplicationTypeId, Guid? NetworkRegistrationProcessId)> GetCompanyAndApplicationDetailsForApprovalAsync(Guid applicationId);
Task<(Guid CompanyId, string CompanyName, string? BusinessPartnerNumber)> GetCompanyAndApplicationDetailsForCreateWalletAsync(Guid applicationId);
IAsyncEnumerable GetInvitedUsersDataByApplicationIdUntrackedAsync(Guid applicationId);
IAsyncEnumerable GetEmailDataUntrackedAsync(Guid applicationId);
diff --git a/src/portalbackend/PortalBackend.PortalEntities/Entities/CompanyApplication.cs b/src/portalbackend/PortalBackend.PortalEntities/Entities/CompanyApplication.cs
index 170514cd1d..e400325c99 100644
--- a/src/portalbackend/PortalBackend.PortalEntities/Entities/CompanyApplication.cs
+++ b/src/portalbackend/PortalBackend.PortalEntities/Entities/CompanyApplication.cs
@@ -66,7 +66,7 @@ public CompanyApplication(Guid id, Guid companyId, CompanyApplicationStatusId ap
public virtual Process? ChecklistProcess { get; set; }
public virtual CompanyApplicationType? CompanyApplicationType { get; set; }
public virtual Company? OnboardingServiceProvider { get; set; }
- public virtual NetworkRegistration? NetworkRegistration { get; private set; }
+ public virtual NetworkRegistration? NetworkRegistration { get; set; }
public virtual Identity? LastEditor { get; private set; }
public virtual CompanyInvitation? CompanyInvitation { get; private set; }
public virtual ICollection Invitations { get; private set; }
diff --git a/src/processes/ApplicationChecklist.Library/ApplicationChecklistEntryTypeIdExtensions.cs b/src/processes/ApplicationChecklist.Library/ApplicationChecklistEntryTypeIdExtensions.cs
index 80ed0ecb54..353ceb28cc 100644
--- a/src/processes/ApplicationChecklist.Library/ApplicationChecklistEntryTypeIdExtensions.cs
+++ b/src/processes/ApplicationChecklist.Library/ApplicationChecklistEntryTypeIdExtensions.cs
@@ -39,15 +39,14 @@ public static IEnumerable GetManualTriggerProcessStepIds(this
public static IEnumerable GetManualTriggerProcessStepIds(this IEnumerable entryTypeIds) =>
ManualProcessStepIds.IntersectBy(entryTypeIds, x => x.Key).SelectMany(x => x.Value).Distinct();
- public static (ProcessStepTypeId ProcessStepTypeId, ApplicationChecklistEntryStatusId ChecklistEntryStatusId) GetNextProcessStepDataForManualTriggerProcessStepId(this ProcessStepTypeId processStepTypeId, bool clearinghouseConnectDisabled) =>
+ public static (ProcessStepTypeId ProcessStepTypeId, ApplicationChecklistEntryStatusId ChecklistEntryStatusId) GetNextProcessStepDataForManualTriggerProcessStepId(this ProcessStepTypeId processStepTypeId) =>
processStepTypeId switch
{
ProcessStepTypeId.RETRIGGER_CLEARING_HOUSE => (ProcessStepTypeId.START_CLEARING_HOUSE, ApplicationChecklistEntryStatusId.TO_DO),
ProcessStepTypeId.RETRIGGER_IDENTITY_WALLET => (ProcessStepTypeId.CREATE_IDENTITY_WALLET, ApplicationChecklistEntryStatusId.TO_DO),
ProcessStepTypeId.RETRIGGER_CREATE_DIM_WALLET => (ProcessStepTypeId.CREATE_DIM_WALLET, ApplicationChecklistEntryStatusId.TO_DO),
ProcessStepTypeId.RETRIGGER_VALIDATE_DID_DOCUMENT => (ProcessStepTypeId.VALIDATE_DID_DOCUMENT, ApplicationChecklistEntryStatusId.TO_DO),
- ProcessStepTypeId.RETRIGGER_SELF_DESCRIPTION_LP when clearinghouseConnectDisabled => (ProcessStepTypeId.ACTIVATE_APPLICATION, ApplicationChecklistEntryStatusId.SKIPPED),
- ProcessStepTypeId.RETRIGGER_SELF_DESCRIPTION_LP when !clearinghouseConnectDisabled => (ProcessStepTypeId.START_SELF_DESCRIPTION_LP, ApplicationChecklistEntryStatusId.TO_DO),
+ ProcessStepTypeId.RETRIGGER_SELF_DESCRIPTION_LP => (ProcessStepTypeId.START_SELF_DESCRIPTION_LP, ApplicationChecklistEntryStatusId.TO_DO),
ProcessStepTypeId.RETRIGGER_BUSINESS_PARTNER_NUMBER_PUSH => (ProcessStepTypeId.CREATE_BUSINESS_PARTNER_NUMBER_PUSH, ApplicationChecklistEntryStatusId.TO_DO),
ProcessStepTypeId.RETRIGGER_BUSINESS_PARTNER_NUMBER_PULL => (ProcessStepTypeId.CREATE_BUSINESS_PARTNER_NUMBER_PULL, ApplicationChecklistEntryStatusId.IN_PROGRESS),
ProcessStepTypeId.TRIGGER_OVERRIDE_CLEARING_HOUSE => (ProcessStepTypeId.START_OVERRIDE_CLEARING_HOUSE, ApplicationChecklistEntryStatusId.TO_DO),
diff --git a/src/registration/ApplicationActivation.Library/ApplicationActivationService.cs b/src/registration/ApplicationActivation.Library/ApplicationActivationService.cs
index 8672b2aedf..32ba5df5a0 100644
--- a/src/registration/ApplicationActivation.Library/ApplicationActivationService.cs
+++ b/src/registration/ApplicationActivation.Library/ApplicationActivationService.cs
@@ -90,7 +90,7 @@ public ApplicationActivationService(
throw new ConflictException($"CompanyApplication {context.ApplicationId} is not in status SUBMITTED");
}
- var (companyId, companyName, businessPartnerNumber, iamIdpAliasse, applicationTypeId, networkRegistrationProcessId) = result;
+ var (companyId, companyName, businessPartnerNumber, sharedIdpAliase, applicationTypeId, networkRegistrationProcessId) = result;
if (string.IsNullOrWhiteSpace(businessPartnerNumber))
{
throw new ConflictException($"BusinessPartnerNumber (bpn) for CompanyApplications {context.ApplicationId} company {companyId} is empty");
@@ -99,7 +99,7 @@ public ApplicationActivationService(
var userRolesRepository = _portalRepositories.GetInstance();
var assignedRoles = await AssignRolesAndBpn(context.ApplicationId, userRolesRepository, applicationRepository, businessPartnerNumber).ConfigureAwait(ConfigureAwaitOptions.None);
await RemoveRegistrationRoles(context.ApplicationId, userRolesRepository).ConfigureAwait(ConfigureAwaitOptions.None);
- await SetTheme(iamIdpAliasse).ConfigureAwait(ConfigureAwaitOptions.None);
+ await SetTheme(sharedIdpAliase).ConfigureAwait(ConfigureAwaitOptions.None);
applicationRepository.AttachAndModifyCompanyApplication(context.ApplicationId, ca =>
{
diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/RegistrationBusinessLogicTest.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/RegistrationBusinessLogicTest.cs
index 0572449a24..fa6e6a68e2 100644
--- a/tests/administration/Administration.Service.Tests/BusinessLogic/RegistrationBusinessLogicTest.cs
+++ b/tests/administration/Administration.Service.Tests/BusinessLogic/RegistrationBusinessLogicTest.cs
@@ -193,12 +193,20 @@ public async Task GetCompanyApplicationDetailsAsync_WithClosedRequest_GetsExpect
#region GetOSPCompanyApplicationDetailsAsync
[Theory]
- [InlineData(null)]
- [InlineData(CompanyApplicationStatusFilter.Closed)]
- [InlineData(CompanyApplicationStatusFilter.InReview)]
- public async Task GetOspCompanyApplicationDetailsAsync_WithDefaultRequest_GetsExpectedEntries(CompanyApplicationStatusFilter? statusFilter)
+ [InlineData(null, null)]
+ [InlineData(null, DateCreatedOrderFilter.ASC)]
+ [InlineData(null, DateCreatedOrderFilter.DESC)]
+ [InlineData(CompanyApplicationStatusFilter.Closed, null)]
+ [InlineData(CompanyApplicationStatusFilter.InReview, null)]
+ [InlineData(CompanyApplicationStatusFilter.Closed, DateCreatedOrderFilter.ASC)]
+ [InlineData(CompanyApplicationStatusFilter.InReview, DateCreatedOrderFilter.ASC)]
+ [InlineData(CompanyApplicationStatusFilter.Closed, DateCreatedOrderFilter.DESC)]
+ [InlineData(CompanyApplicationStatusFilter.InReview, DateCreatedOrderFilter.DESC)]
+ public async Task GetOspCompanyApplicationDetailsAsync_WithDefaultRequest_GetsExpectedEntries(CompanyApplicationStatusFilter? statusFilter, DateCreatedOrderFilter? dateCreatedOrderFilter)
{
// Arrange
+ var companyName = _fixture.Create();
+ var externalId = _fixture.Create();
var data = _fixture.CreateMany<(Guid Id, Guid CompanyId, CompanyApplicationStatusId CompanyApplicationStatusId, DateTimeOffset Created)>(10)
.Select(x => new CompanyApplication(x.Id, x.CompanyId, x.CompanyApplicationStatusId, CompanyApplicationTypeId.EXTERNAL, x.Created)
{
@@ -207,16 +215,21 @@ public async Task GetOspCompanyApplicationDetailsAsync_WithDefaultRequest_GetsEx
Name = _fixture.Create(),
BusinessPartnerNumber = _fixture.Create(),
},
+ NetworkRegistration = new NetworkRegistration(Guid.NewGuid(), _fixture.Create(), x.CompanyId, Guid.NewGuid(), Guid.NewGuid(), x.Id, x.Created)
+ {
+ ExternalId = _fixture.Create(),
+ DateCreated = _fixture.Create(),
+ },
DateLastChanged = _fixture.Create()
}).ToImmutableList();
var queryData = new AsyncEnumerableStub(data).AsQueryable();
- A.CallTo(() => _applicationRepository.GetExternalCompanyApplicationsFilteredQuery(A._, A._, A>._))
+ A.CallTo(() => _applicationRepository.GetExternalCompanyApplicationsFilteredQuery(A._, A._, A._, A>._))
.Returns(queryData);
// Act
- var result = await _logic.GetOspCompanyDetailsAsync(0, 3, statusFilter, null);
+ var result = await _logic.GetOspCompanyDetailsAsync(0, 3, statusFilter, companyName, externalId, dateCreatedOrderFilter);
// Assert
Assert.IsType>(result);
@@ -224,25 +237,41 @@ public async Task GetOspCompanyApplicationDetailsAsync_WithDefaultRequest_GetsEx
switch (statusFilter)
{
case CompanyApplicationStatusFilter.Closed:
- A.CallTo(() => _applicationRepository.GetExternalCompanyApplicationsFilteredQuery(CompanyId, null, A>.That.IsSameSequenceAs(new[] { CompanyApplicationStatusId.CONFIRMED, CompanyApplicationStatusId.DECLINED }))).MustHaveHappenedOnceExactly();
+ A.CallTo(() => _applicationRepository.GetExternalCompanyApplicationsFilteredQuery(CompanyId, companyName, externalId, A>.That.IsSameSequenceAs(new[] { CompanyApplicationStatusId.CONFIRMED, CompanyApplicationStatusId.DECLINED }))).MustHaveHappenedOnceExactly();
break;
case CompanyApplicationStatusFilter.InReview:
- A.CallTo(() => _applicationRepository.GetExternalCompanyApplicationsFilteredQuery(CompanyId, null, A>.That.IsSameSequenceAs(new[] { CompanyApplicationStatusId.SUBMITTED }))).MustHaveHappenedOnceExactly();
+ A.CallTo(() => _applicationRepository.GetExternalCompanyApplicationsFilteredQuery(CompanyId, companyName, externalId, A>.That.IsSameSequenceAs(new[] { CompanyApplicationStatusId.SUBMITTED }))).MustHaveHappenedOnceExactly();
break;
default:
- A.CallTo(() => _applicationRepository.GetExternalCompanyApplicationsFilteredQuery(CompanyId, null, A>.That.IsSameSequenceAs(new[] { CompanyApplicationStatusId.SUBMITTED, CompanyApplicationStatusId.CONFIRMED, CompanyApplicationStatusId.DECLINED }))).MustHaveHappenedOnceExactly();
+ A.CallTo(() => _applicationRepository.GetExternalCompanyApplicationsFilteredQuery(CompanyId, companyName, externalId, A>.That.IsSameSequenceAs(new[] { CompanyApplicationStatusId.SUBMITTED, CompanyApplicationStatusId.CONFIRMED, CompanyApplicationStatusId.DECLINED }))).MustHaveHappenedOnceExactly();
break;
}
result.Meta.NumberOfElements.Should().Be(10);
- var sorted = data.OrderByDescending(application => application.DateCreated).ToImmutableArray();
+ var sorted = dateCreatedOrderFilter switch
+ {
+ DateCreatedOrderFilter.ASC => data.OrderBy(application => application.Company!.DateCreated).Take(3).ToImmutableArray(),
+ DateCreatedOrderFilter.DESC => data.OrderByDescending(application => application.Company!.DateCreated).Take(3).ToImmutableArray(),
+ _ => data.OrderByDescending(application => application.Company!.DateCreated).Take(3).ToImmutableArray()
+ };
result.Content.Should().HaveCount(3).And.Satisfy(
x => x.ApplicationId == sorted[0].Id && x.CompanyApplicationStatusId == sorted[0].ApplicationStatusId && x.DateCreated == sorted[0].DateCreated && x.DateLastChanged == sorted[0].DateLastChanged && x.CompanyId == sorted[0].CompanyId && x.CompanyName == sorted[0].Company!.Name && x.BusinessPartnerNumber == sorted[0].Company!.BusinessPartnerNumber,
x => x.ApplicationId == sorted[1].Id && x.CompanyApplicationStatusId == sorted[1].ApplicationStatusId && x.DateCreated == sorted[1].DateCreated && x.DateLastChanged == sorted[1].DateLastChanged && x.CompanyId == sorted[1].CompanyId && x.CompanyName == sorted[1].Company!.Name && x.BusinessPartnerNumber == sorted[1].Company!.BusinessPartnerNumber,
x => x.ApplicationId == sorted[2].Id && x.CompanyApplicationStatusId == sorted[2].ApplicationStatusId && x.DateCreated == sorted[2].DateCreated && x.DateLastChanged == sorted[2].DateLastChanged && x.CompanyId == sorted[2].CompanyId && x.CompanyName == sorted[2].Company!.Name && x.BusinessPartnerNumber == sorted[2].Company!.BusinessPartnerNumber
);
+
+ switch (dateCreatedOrderFilter)
+ {
+ case DateCreatedOrderFilter.ASC:
+ result.Content.Should().BeInAscendingOrder(x => x.DateCreated);
+ break;
+ case null:
+ case DateCreatedOrderFilter.DESC:
+ result.Content.Should().BeInDescendingOrder(x => x.DateCreated);
+ break;
+ }
}
#endregion
@@ -752,15 +781,14 @@ public async Task TriggerChecklistAsync_WithFailingChecklistServiceCall_ReturnsE
}
[Theory]
- [InlineData(ApplicationChecklistEntryTypeId.CLEARING_HOUSE, ProcessStepTypeId.RETRIGGER_CLEARING_HOUSE, ProcessStepTypeId.START_CLEARING_HOUSE, ApplicationChecklistEntryStatusId.TO_DO, false)]
- [InlineData(ApplicationChecklistEntryTypeId.IDENTITY_WALLET, ProcessStepTypeId.RETRIGGER_IDENTITY_WALLET, ProcessStepTypeId.CREATE_IDENTITY_WALLET, ApplicationChecklistEntryStatusId.TO_DO, false)]
- [InlineData(ApplicationChecklistEntryTypeId.IDENTITY_WALLET, ProcessStepTypeId.RETRIGGER_CREATE_DIM_WALLET, ProcessStepTypeId.CREATE_DIM_WALLET, ApplicationChecklistEntryStatusId.TO_DO, false)]
- [InlineData(ApplicationChecklistEntryTypeId.IDENTITY_WALLET, ProcessStepTypeId.RETRIGGER_VALIDATE_DID_DOCUMENT, ProcessStepTypeId.VALIDATE_DID_DOCUMENT, ApplicationChecklistEntryStatusId.TO_DO, false)]
- [InlineData(ApplicationChecklistEntryTypeId.SELF_DESCRIPTION_LP, ProcessStepTypeId.RETRIGGER_SELF_DESCRIPTION_LP, ProcessStepTypeId.START_SELF_DESCRIPTION_LP, ApplicationChecklistEntryStatusId.TO_DO, false)]
- [InlineData(ApplicationChecklistEntryTypeId.SELF_DESCRIPTION_LP, ProcessStepTypeId.RETRIGGER_SELF_DESCRIPTION_LP, ProcessStepTypeId.ACTIVATE_APPLICATION, ApplicationChecklistEntryStatusId.SKIPPED, true)]
- [InlineData(ApplicationChecklistEntryTypeId.BUSINESS_PARTNER_NUMBER, ProcessStepTypeId.RETRIGGER_BUSINESS_PARTNER_NUMBER_PUSH, ProcessStepTypeId.CREATE_BUSINESS_PARTNER_NUMBER_PUSH, ApplicationChecklistEntryStatusId.TO_DO, false)]
- [InlineData(ApplicationChecklistEntryTypeId.BUSINESS_PARTNER_NUMBER, ProcessStepTypeId.RETRIGGER_BUSINESS_PARTNER_NUMBER_PULL, ProcessStepTypeId.CREATE_BUSINESS_PARTNER_NUMBER_PULL, ApplicationChecklistEntryStatusId.IN_PROGRESS, false)]
- public async Task TriggerChecklistAsync_WithValidData_ReturnsExpected(ApplicationChecklistEntryTypeId typeId, ProcessStepTypeId stepId, ProcessStepTypeId nextStepId, ApplicationChecklistEntryStatusId statusId, bool clearinghouseConnectDisabled)
+ [InlineData(ApplicationChecklistEntryTypeId.CLEARING_HOUSE, ProcessStepTypeId.RETRIGGER_CLEARING_HOUSE, ProcessStepTypeId.START_CLEARING_HOUSE, ApplicationChecklistEntryStatusId.TO_DO)]
+ [InlineData(ApplicationChecklistEntryTypeId.IDENTITY_WALLET, ProcessStepTypeId.RETRIGGER_IDENTITY_WALLET, ProcessStepTypeId.CREATE_IDENTITY_WALLET, ApplicationChecklistEntryStatusId.TO_DO)]
+ [InlineData(ApplicationChecklistEntryTypeId.IDENTITY_WALLET, ProcessStepTypeId.RETRIGGER_CREATE_DIM_WALLET, ProcessStepTypeId.CREATE_DIM_WALLET, ApplicationChecklistEntryStatusId.TO_DO)]
+ [InlineData(ApplicationChecklistEntryTypeId.IDENTITY_WALLET, ProcessStepTypeId.RETRIGGER_VALIDATE_DID_DOCUMENT, ProcessStepTypeId.VALIDATE_DID_DOCUMENT, ApplicationChecklistEntryStatusId.TO_DO)]
+ [InlineData(ApplicationChecklistEntryTypeId.SELF_DESCRIPTION_LP, ProcessStepTypeId.RETRIGGER_SELF_DESCRIPTION_LP, ProcessStepTypeId.START_SELF_DESCRIPTION_LP, ApplicationChecklistEntryStatusId.TO_DO)]
+ [InlineData(ApplicationChecklistEntryTypeId.BUSINESS_PARTNER_NUMBER, ProcessStepTypeId.RETRIGGER_BUSINESS_PARTNER_NUMBER_PUSH, ProcessStepTypeId.CREATE_BUSINESS_PARTNER_NUMBER_PUSH, ApplicationChecklistEntryStatusId.TO_DO)]
+ [InlineData(ApplicationChecklistEntryTypeId.BUSINESS_PARTNER_NUMBER, ProcessStepTypeId.RETRIGGER_BUSINESS_PARTNER_NUMBER_PULL, ProcessStepTypeId.CREATE_BUSINESS_PARTNER_NUMBER_PULL, ApplicationChecklistEntryStatusId.IN_PROGRESS)]
+ public async Task TriggerChecklistAsync_WithValidData_ReturnsExpected(ApplicationChecklistEntryTypeId typeId, ProcessStepTypeId stepId, ProcessStepTypeId nextStepId, ApplicationChecklistEntryStatusId statusId)
{
// Arrange
var checklistEntry = new ApplicationChecklistEntry(Guid.NewGuid(), typeId,
@@ -795,7 +823,6 @@ public async Task TriggerChecklistAsync_WithValidData_ReturnsExpected(Applicatio
//Act
var settings = A.Fake();
- settings.ClearinghouseConnectDisabled = clearinghouseConnectDisabled;
A.CallTo(() => _options.Value).Returns(settings);
var logic = new RegistrationBusinessLogic(_portalRepositories, _options, _checklistService, _clearinghouseBusinessLogic, _sdFactoryBusinessLogic, _dimBusinessLogic, _issuerComponentBusinessLogic, _provisioningManager, _mailingProcessCreation, _identityService, _logger);
await logic.TriggerChecklistAsync(applicationId, typeId, stepId);
diff --git a/tests/administration/Administration.Service.Tests/Controllers/RegistrationControllerTest.cs b/tests/administration/Administration.Service.Tests/Controllers/RegistrationControllerTest.cs
index 2b5035c287..4fd1557ad5 100644
--- a/tests/administration/Administration.Service.Tests/Controllers/RegistrationControllerTest.cs
+++ b/tests/administration/Administration.Service.Tests/Controllers/RegistrationControllerTest.cs
@@ -74,15 +74,22 @@ public async Task GetCompanyApplicationDetailsAsync_ReturnsCompanyApplicationDet
public async Task GetOspCompanyApplicationDetailsAsync_ReturnsCompanyApplicationDetails()
{
//Arrange
+ var page = _fixture.Create();
+ var size = _fixture.Create();
+ var companyApplicationStatusFilter = _fixture.Create();
+ var companyName = _fixture.Create();
+ var externalId = _fixture.Create();
+ var dateCreatedOrderFilter = _fixture.Create();
+
var paginationResponse = new Pagination.Response(new Pagination.Metadata(15, 1, 1, 15), _fixture.CreateMany(5));
- A.CallTo(() => _logic.GetOspCompanyDetailsAsync(0, 15, null, null))
+ A.CallTo(() => _logic.GetOspCompanyDetailsAsync(A._, A._, A._, A._, A._, A._))
.Returns(paginationResponse);
//Act
- var result = await _controller.GetOspCompanyDetailsAsync(0, 15, null, null);
+ var result = await _controller.GetOspCompanyDetailsAsync(page, size, companyApplicationStatusFilter, companyName, externalId, dateCreatedOrderFilter);
//Assert
- A.CallTo(() => _logic.GetOspCompanyDetailsAsync(0, 15, null, null)).MustHaveHappenedOnceExactly();
+ A.CallTo(() => _logic.GetOspCompanyDetailsAsync(page, size, companyApplicationStatusFilter, companyName, externalId, dateCreatedOrderFilter)).MustHaveHappenedOnceExactly();
Assert.IsType>(result);
result.Content.Should().HaveCount(5);
}
diff --git a/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppChangeBusinessLogicTest.cs b/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppChangeBusinessLogicTest.cs
index 0ffc884c67..98900b5997 100644
--- a/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppChangeBusinessLogicTest.cs
+++ b/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppChangeBusinessLogicTest.cs
@@ -149,6 +149,9 @@ public async Task AddActiveAppUserRoleAsync_ExecutesSuccessfully()
A.CallTo(() => _portalRepositories.GetInstance().GetInsertActiveAppUserRoleDataAsync(appId, OfferTypeId.APP))
.Returns((true, appName, _identity.CompanyId, clientIds));
+ A.CallTo(() => _userRolesRepository.GetUserRolesForOfferIdAsync(appId))
+ .Returns(new[] { "Exsiting Role" }.ToAsyncEnumerable());
+
IEnumerable? userRoles = null;
A.CallTo(() => _userRolesRepository.CreateAppUserRoles(A>._))
.ReturnsLazily((IEnumerable<(Guid AppId, string Role)> appRoles) =>
@@ -226,6 +229,89 @@ public async Task AddActiveAppUserRoleAsync_ExecutesSuccessfully()
);
}
+ [Fact]
+ public async Task AddActiveAppUserRoleAsync_WithExistingData_NoRowEffecting()
+ {
+ //Arrange
+ var appId = _fixture.Create();
+ var appName = _fixture.Create();
+ var appAssignedRoleDesc = _fixture.CreateMany(3).Select(role => new AppUserRole(role, _fixture.CreateMany(2).ToImmutableArray())).ToImmutableArray();
+ var clientIds = new[] { "client" };
+
+ A.CallTo(() => _portalRepositories.GetInstance().GetInsertActiveAppUserRoleDataAsync(appId, OfferTypeId.APP))
+ .Returns((true, appName, _identity.CompanyId, clientIds));
+
+ A.CallTo(() => _userRolesRepository.GetUserRolesForOfferIdAsync(appId))
+ .Returns(appAssignedRoleDesc.Select(x => x.Role).ToAsyncEnumerable());
+
+ IEnumerable? userRoles = null;
+ A.CallTo(() => _userRolesRepository.CreateAppUserRoles(A>._))
+ .ReturnsLazily((IEnumerable<(Guid AppId, string Role)> appRoles) =>
+ {
+ userRoles = appRoles.Select(x => new UserRole(Guid.NewGuid(), x.Role, x.AppId)).ToImmutableArray();
+ return userRoles;
+ });
+
+ var userRoleDescriptions = new List>();
+ A.CallTo(() => _userRolesRepository.CreateAppUserRoleDescriptions(A>._))
+ .ReturnsLazily((IEnumerable<(Guid RoleId, string LanguageCode, string Description)> roleLanguageDescriptions) =>
+ {
+ var createdUserRoleDescriptions = roleLanguageDescriptions.Select(x => new UserRoleDescription(x.RoleId, x.LanguageCode, x.Description)).ToImmutableArray();
+ userRoleDescriptions.Add(createdUserRoleDescriptions);
+ return createdUserRoleDescriptions;
+ });
+ var existingOffer = _fixture.Create();
+ existingOffer.DateLastChanged = DateTimeOffset.UtcNow;
+ A.CallTo(() => _offerRepository.AttachAndModifyOffer(appId, A>._, A?>._))
+ .Invokes((Guid _, Action setOptionalParameters, Action? initializeParemeters) =>
+ {
+ initializeParemeters?.Invoke(existingOffer);
+ setOptionalParameters(existingOffer);
+ });
+ A.CallTo(() => _notificationService.CreateNotifications(A>._, A._, A>._, A._, A._))
+ .Returns(_fixture.CreateMany(4).AsFakeIAsyncEnumerable(out var createNotificationsResultAsyncEnumerator));
+
+ //Act
+ var result = await _sut.AddActiveAppUserRoleAsync(appId, appAssignedRoleDesc);
+
+ //Assert
+ A.CallTo(() => _offerRepository.GetInsertActiveAppUserRoleDataAsync(appId, OfferTypeId.APP)).MustHaveHappened();
+
+ A.CallTo(() => _userRolesRepository.CreateAppUserRoles(A>._)).MustHaveHappenedOnceExactly();
+ userRoles.Should().NotBeNull()
+ .And.HaveCount(0);
+
+ A.CallTo(() => _userRolesRepository.CreateAppUserRoleDescriptions(A>._)).MustNotHaveHappened();
+ userRoleDescriptions.Should().NotBeNull()
+ .And.HaveCount(0);
+ A.CallTo(() => _offerRepository.AttachAndModifyOffer(appId, A>._, A?>._)).MustNotHaveHappened();
+ A.CallTo(() => _notificationService.CreateNotifications(A>._, A._, A>._, A._, A._))
+ .MustNotHaveHappened();
+ A.CallTo(() => createNotificationsResultAsyncEnumerator.MoveNextAsync())
+ .MustNotHaveHappened();
+ A.CallTo(() => _provisioningManager.AddRolesToClientAsync("client", A>.That.IsSameSequenceAs(appAssignedRoleDesc.Select(x => x.Role))))
+ .MustNotHaveHappened();
+
+ result.Should().NotBeNull()
+ .And.HaveCount(0);
+ }
+
+ [Fact]
+ public async Task AddDuplicateActiveAppUserRoleAsync_ThrowsControllerArgumentException()
+ {
+ //Arrange
+ var appId = _fixture.Create();
+ var roleId = _fixture.Create();
+ var appAssignedRoleDesc = _fixture.CreateMany(3).Select(role => new AppUserRole(roleId, _fixture.CreateMany(2).ToImmutableArray())).ToImmutableArray();
+
+ //Act
+ async Task Act() => await _sut.AddActiveAppUserRoleAsync(appId, appAssignedRoleDesc);
+
+ //Assert
+ var error = await Assert.ThrowsAsync(Act);
+ error.Message.Should().Be($"Roles are ambiguous: {roleId},{roleId}");
+ }
+
[Fact]
public async Task AddActiveAppUserRoleAsync_WithCompanyUserIdNotSet_ThrowsForbiddenException()
{
diff --git a/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppReleaseBusinessLogicTest.cs b/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppReleaseBusinessLogicTest.cs
index 6c846dc548..cf16cd3f72 100644
--- a/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppReleaseBusinessLogicTest.cs
+++ b/tests/marketplace/Apps.Service.Tests/BusinessLogic/AppReleaseBusinessLogicTest.cs
@@ -145,6 +145,9 @@ public async Task CreateServiceOffering_WithValidDataAndEmptyDescriptions_Return
A.CallTo(() => _offerRepository.IsProviderCompanyUserAsync(appId, _identity.CompanyId, OfferTypeId.APP))
.Returns((true, true));
+ A.CallTo(() => _userRolesRepository.GetUserRolesForOfferIdAsync(appId))
+ .Returns(new[] { "Exsiting Role" }.ToAsyncEnumerable());
+
IEnumerable? userRoles = null;
A.CallTo(() => _userRolesRepository.CreateAppUserRoles(A>._))
.ReturnsLazily((IEnumerable<(Guid AppId, string Role)> appRoles) =>
@@ -214,6 +217,78 @@ public async Task CreateServiceOffering_WithValidDataAndEmptyDescriptions_Return
);
}
+ [Fact]
+ public async Task CreateServiceOffering_WithExistingData_NoRowEffecting()
+ {
+ // Arrange
+ var appId = _fixture.Create();
+ var appUserRoles = _fixture.CreateMany(3).Select(role => new AppUserRole(role, _fixture.CreateMany(2).ToImmutableArray())).ToImmutableArray();
+
+ A.CallTo(() => _offerRepository.IsProviderCompanyUserAsync(appId, _identity.CompanyId, OfferTypeId.APP))
+ .Returns((true, true));
+
+ A.CallTo(() => _userRolesRepository.GetUserRolesForOfferIdAsync(appId))
+ .Returns(appUserRoles.Select(x => x.Role).ToAsyncEnumerable());
+
+ IEnumerable? userRoles = null;
+ A.CallTo(() => _userRolesRepository.CreateAppUserRoles(A>._))
+ .ReturnsLazily((IEnumerable<(Guid AppId, string Role)> appRoles) =>
+ {
+ userRoles = appRoles.Select(x => new UserRole(Guid.NewGuid(), x.Role, x.AppId)).ToImmutableArray();
+ return userRoles;
+ });
+
+ var userRoleDescriptions = new List>();
+ A.CallTo(() => _userRolesRepository.CreateAppUserRoleDescriptions(A>._))
+ .ReturnsLazily((IEnumerable<(Guid RoleId, string LanguageCode, string Description)> roleLanguageDescriptions) =>
+ {
+ var createdUserRoleDescriptions = roleLanguageDescriptions.Select(x => new UserRoleDescription(x.RoleId, x.LanguageCode, x.Description)).ToImmutableArray();
+ userRoleDescriptions.Add(createdUserRoleDescriptions);
+ return createdUserRoleDescriptions;
+ });
+ var existingOffer = _fixture.Create();
+ existingOffer.DateLastChanged = DateTimeOffset.UtcNow;
+ A.CallTo(() => _offerRepository.AttachAndModifyOffer(appId, A>._, A?>._))
+ .Invokes((Guid _, Action setOptionalParameters, Action? initializeParemeters) =>
+ {
+ initializeParemeters?.Invoke(existingOffer);
+ setOptionalParameters(existingOffer);
+ });
+ // Act
+ var result = await _sut.AddAppUserRoleAsync(appId, appUserRoles);
+
+ // Assert
+ A.CallTo(() => _offerRepository.IsProviderCompanyUserAsync(A._, A._, A._)).MustHaveHappened();
+
+ A.CallTo(() => _userRolesRepository.CreateAppUserRoles(A>._)).MustHaveHappenedOnceExactly();
+ userRoles.Should().NotBeNull()
+ .And.HaveCount(0);
+
+ A.CallTo(() => _offerRepository.AttachAndModifyOffer(appId, A>._, A?>._)).MustNotHaveHappened();
+ A.CallTo(() => _userRolesRepository.CreateAppUserRoleDescriptions(A>._)).MustNotHaveHappened();
+ userRoleDescriptions.Should().NotBeNull()
+ .And.HaveCount(0);
+
+ result.Should().NotBeNull()
+ .And.HaveCount(0);
+ }
+
+ [Fact]
+ public async Task CreateServiceOffering_WithValidButDuplicateData_ThrowsControllerArgumentException()
+ {
+ // Arrange
+ var appId = _fixture.Create();
+ var roleId = _fixture.Create();
+ var appUserRoles = _fixture.CreateMany(3).Select(role => new AppUserRole(roleId, _fixture.CreateMany(2).ToImmutableArray())).ToImmutableArray();
+
+ // Act
+ async Task Act() => await _sut.AddAppUserRoleAsync(appId, appUserRoles);
+
+ // Assert
+ var error = await Assert.ThrowsAsync(Act);
+ error.Message.Should().Be($"Roles are ambiguous: {roleId},{roleId}");
+ }
+
#region AddAppAsync
[Fact]