diff --git a/src/administration/Administration.Service/BusinessLogic/SubscriptionConfigurationBusinessLogic.cs b/src/administration/Administration.Service/BusinessLogic/SubscriptionConfigurationBusinessLogic.cs
index 7eb232315c..8b58cf300a 100644
--- a/src/administration/Administration.Service/BusinessLogic/SubscriptionConfigurationBusinessLogic.cs
+++ b/src/administration/Administration.Service/BusinessLogic/SubscriptionConfigurationBusinessLogic.cs
@@ -25,35 +25,32 @@
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities;
+using Org.Eclipse.TractusX.Portal.Backend.Processes.Library;
using Org.Eclipse.TractusX.Portal.Backend.Processes.OfferSubscription.Library;
using Org.Eclipse.TractusX.Portal.Backend.Processes.OfferSubscription.Library.Extensions;
namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLogic;
-public class SubscriptionConfigurationBusinessLogic : ISubscriptionConfigurationBusinessLogic
+public class SubscriptionConfigurationBusinessLogic(
+ IOfferSubscriptionProcessService offerSubscriptionProcessService,
+ IPortalRepositories portalRepositories,
+ IIdentityService identityService)
+ : ISubscriptionConfigurationBusinessLogic
{
- private readonly IOfferSubscriptionProcessService _offerSubscriptionProcessService;
- private readonly IPortalRepositories _portalRepositories;
- private readonly IIdentityData _identityData;
-
- public SubscriptionConfigurationBusinessLogic(IOfferSubscriptionProcessService offerSubscriptionProcessService, IPortalRepositories portalRepositories, IIdentityService identityService)
- {
- _offerSubscriptionProcessService = offerSubscriptionProcessService;
- _portalRepositories = portalRepositories;
- _identityData = identityService.IdentityData;
- }
+ private readonly IIdentityData _identityData = identityService.IdentityData;
///
public async Task GetProviderCompanyDetailsAsync()
{
var companyId = _identityData.CompanyId;
- var result = await _portalRepositories.GetInstance()
+ var result = await portalRepositories.GetInstance()
.GetProviderCompanyDetailAsync(CompanyRoleId.SERVICE_PROVIDER, companyId)
.ConfigureAwait(ConfigureAwaitOptions.None);
if (result == default)
{
throw ConflictException.Create(AdministrationSubscriptionConfigurationErrors.SUBSCRIPTION_CONFLICT_COMPANY_NOT_FOUND, new ErrorParameter[] { new(nameof(companyId), companyId.ToString()) });
}
+
if (!result.IsProviderCompany)
{
throw ForbiddenException.Create(AdministrationSubscriptionConfigurationErrors.SUBSCRIPTION_FORBIDDEN_COMPANY_NOT_SERVICE_PROVIDER, new ErrorParameter[] { new(nameof(companyId), companyId.ToString()) });
@@ -78,7 +75,7 @@ public Task SetProviderCompanyDetailsAsync(ProviderDetailData data)
private async Task SetOfferProviderCompanyDetailsInternalAsync(ProviderDetailData data, Guid companyId)
{
- var companyRepository = _portalRepositories.GetInstance();
+ var companyRepository = portalRepositories.GetInstance();
var providerDetailData = await companyRepository
.GetProviderCompanyDetailsExistsForUser(companyId)
.ConfigureAwait(ConfigureAwaitOptions.None);
@@ -92,9 +89,14 @@ private async Task SetOfferProviderCompanyDetailsInternalAsync(ProviderDetailDat
{
companyRepository.AttachAndModifyProviderCompanyDetails(
providerDetailData.ProviderCompanyDetailId,
- details => { details.AutoSetupUrl = providerDetailData.Url; },
details =>
{
+ details.AutoSetupUrl = providerDetailData.Url;
+ details.AutoSetupCallbackUrl = providerDetailData.CallbackUrl;
+ },
+ details =>
+ {
+ details.AutoSetupCallbackUrl = data.CallbackUrl;
details.AutoSetupUrl = data.Url;
details.DateLastChanged = DateTimeOffset.UtcNow;
});
@@ -106,9 +108,35 @@ private async Task SetOfferProviderCompanyDetailsInternalAsync(ProviderDetailDat
hasChanges = true;
}
+ if (providerDetailData.CallbackUrl is not null && data.CallbackUrl is null)
+ {
+ await HandleOfferSetupProcesses(companyId, companyRepository).ConfigureAwait(ConfigureAwaitOptions.None);
+ hasChanges = true;
+ }
+
if (hasChanges)
{
- await _portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
+ await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
+ }
+ }
+
+ private async Task HandleOfferSetupProcesses(Guid companyId, ICompanyRepository companyRepository)
+ {
+ var processData = await companyRepository
+ .GetOfferSubscriptionProcessesForCompanyId(companyId)
+ .ToListAsync()
+ .ConfigureAwait(false);
+
+ foreach (var context in processData
+ .Where(x => x.Process != null && x.ProcessSteps?.Any(ps => ps is
+ {
+ ProcessStepStatusId: ProcessStepStatusId.TODO,
+ ProcessStepTypeId: ProcessStepTypeId.RETRIGGER_PROVIDER
+ }) == true)
+ .Select(data => data.CreateManualProcessData(ProcessStepTypeId.RETRIGGER_PROVIDER, portalRepositories, () => $"processId {data.Process!.Id}")))
+ {
+ context.FinalizeProcessStep();
+ context.ScheduleProcessSteps(Enumerable.Repeat(ProcessStepTypeId.AWAIT_START_AUTOSETUP, 1));
}
}
@@ -129,11 +157,7 @@ private static async Task HandleCreateProviderCompanyDetails(ProviderDetailData
companyRepository.CreateProviderCompanyDetail(companyId, data.Url!, providerDetails =>
{
- if (data.CallbackUrl != null)
- {
- providerDetails.AutoSetupCallbackUrl = data.CallbackUrl;
- }
-
+ providerDetails.AutoSetupCallbackUrl = data.CallbackUrl;
providerDetails.DateLastChanged = DateTimeOffset.UtcNow;
});
}
@@ -158,18 +182,17 @@ public Task RetriggerProviderCallback(Guid offerSubscriptionId) =>
public Task RetriggerCreateDimTechnicalUser(Guid offerSubscriptionId) =>
TriggerProcessStep(offerSubscriptionId, ProcessStepTypeId.RETRIGGER_OFFERSUBSCRIPTION_CREATE_DIM_TECHNICAL_USER, true);
- ///
private async Task TriggerProcessStep(Guid offerSubscriptionId, ProcessStepTypeId stepToTrigger, bool mustBePending)
{
var nextStep = stepToTrigger.GetOfferSubscriptionStepToRetrigger();
- var context = await _offerSubscriptionProcessService.VerifySubscriptionAndProcessSteps(offerSubscriptionId, stepToTrigger, null, mustBePending)
+ var context = await offerSubscriptionProcessService.VerifySubscriptionAndProcessSteps(offerSubscriptionId, stepToTrigger, null, mustBePending)
.ConfigureAwait(ConfigureAwaitOptions.None);
- _offerSubscriptionProcessService.FinalizeProcessSteps(context, Enumerable.Repeat(nextStep, 1));
- await _portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
+ offerSubscriptionProcessService.FinalizeProcessSteps(context, Enumerable.Repeat(nextStep, 1));
+ await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
}
///
public IAsyncEnumerable GetProcessStepsForSubscription(Guid offerSubscriptionId) =>
- _portalRepositories.GetInstance().GetProcessStepsForSubscription(offerSubscriptionId);
+ portalRepositories.GetInstance().GetProcessStepsForSubscription(offerSubscriptionId);
}
diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/CompanyRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/CompanyRepository.cs
index 137494b729..df1dca677d 100644
--- a/src/portalbackend/PortalBackend.DBAccess/Repositories/CompanyRepository.cs
+++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/CompanyRepository.cs
@@ -132,10 +132,10 @@ public IAsyncEnumerable GetAllMemberCompaniesBPNAsync(IEnumerable
- public Task<(Guid ProviderCompanyDetailId, string Url)> GetProviderCompanyDetailsExistsForUser(Guid companyId) =>
+ public Task<(Guid ProviderCompanyDetailId, string Url, string? CallbackUrl)> GetProviderCompanyDetailsExistsForUser(Guid companyId) =>
context.ProviderCompanyDetails.AsNoTracking()
.Where(details => details.CompanyId == companyId)
- .Select(details => new ValueTuple(details.Id, details.AutoSetupUrl))
+ .Select(details => new ValueTuple(details.Id, details.AutoSetupUrl, details.AutoSetupCallbackUrl))
.SingleOrDefaultAsync();
///
@@ -458,4 +458,14 @@ public Task IsExistingCompany(Guid companyId) =>
.Where(x => x.BusinessPartnerNumber == bpn)
.Select(x => new ValueTuple>(true, x.Id, x.CompanyApplications.Where(a => a.ApplicationStatusId == CompanyApplicationStatusId.SUBMITTED).Select(a => a.Id)))
.SingleOrDefaultAsync();
+
+ public IAsyncEnumerable GetOfferSubscriptionProcessesForCompanyId(Guid companyId) =>
+ context.Companies
+ .Where(c => c.Id == companyId)
+ .SelectMany(c => c.ProvidedOffers.SelectMany(po =>
+ po.OfferSubscriptions.Select(os =>
+ new VerifyProcessData(
+ os.Process,
+ os.Process!.ProcessSteps.Where(ps => ps.ProcessStepStatusId == ProcessStepStatusId.TODO)))))
+ .ToAsyncEnumerable();
}
diff --git a/src/portalbackend/PortalBackend.DBAccess/Repositories/ICompanyRepository.cs b/src/portalbackend/PortalBackend.DBAccess/Repositories/ICompanyRepository.cs
index 55eecc9b07..e050ee01c3 100644
--- a/src/portalbackend/PortalBackend.DBAccess/Repositories/ICompanyRepository.cs
+++ b/src/portalbackend/PortalBackend.DBAccess/Repositories/ICompanyRepository.cs
@@ -64,7 +64,7 @@ public interface ICompanyRepository
/// true if the company exists for the given user, otherwise false
Task<(bool IsValidCompanyId, bool IsCompanyRoleOwner)> IsValidCompanyRoleOwner(Guid companyId, IEnumerable companyRoleIds);
- Task<(Guid ProviderCompanyDetailId, string Url)> GetProviderCompanyDetailsExistsForUser(Guid companyId);
+ Task<(Guid ProviderCompanyDetailId, string Url, string? CallbackUrl)> GetProviderCompanyDetailsExistsForUser(Guid companyId);
///
/// Creates service provider company details
@@ -183,4 +183,5 @@ public interface ICompanyRepository
Task<(Guid Id, IEnumerable<(UniqueIdentifierId Id, string Value)> UniqueIdentifiers, string? BusinessPartnerNumber, string CountryCode)> GetCompanyByProcessId(Guid processId);
Task IsExistingCompany(Guid companyId);
Task<(bool Exists, Guid CompanyId, IEnumerable SubmittedCompanyApplicationId)> GetCompanyIdByBpn(string bpn);
+ IAsyncEnumerable GetOfferSubscriptionProcessesForCompanyId(Guid companyId);
}
diff --git a/tests/administration/Administration.Service.Tests/BusinessLogic/SubscriptionConfigurationBusinessLogicTests.cs b/tests/administration/Administration.Service.Tests/BusinessLogic/SubscriptionConfigurationBusinessLogicTests.cs
index e7b2531e2a..a30465dbcc 100644
--- a/tests/administration/Administration.Service.Tests/BusinessLogic/SubscriptionConfigurationBusinessLogicTests.cs
+++ b/tests/administration/Administration.Service.Tests/BusinessLogic/SubscriptionConfigurationBusinessLogicTests.cs
@@ -39,6 +39,7 @@ public class SubscriptionConfigurationBusinessLogicTests
private readonly IIdentityData _identity;
private readonly ICompanyRepository _companyRepository;
+ private readonly IProcessStepRepository _processStepRepository;
private readonly ICollection _serviceProviderDetails;
private static readonly Guid OfferSubscriptionId = Guid.NewGuid();
@@ -47,7 +48,6 @@ public class SubscriptionConfigurationBusinessLogicTests
private readonly IPortalRepositories _portalRepositories;
private readonly IFixture _fixture;
private readonly ISubscriptionConfigurationBusinessLogic _sut;
- private readonly IIdentityService _identityService;
public SubscriptionConfigurationBusinessLogicTests()
{
@@ -56,23 +56,25 @@ public SubscriptionConfigurationBusinessLogicTests()
_offerSubscriptionsRepository = A.Fake();
_companyRepository = A.Fake();
+ _processStepRepository = A.Fake();
_portalRepositories = A.Fake();
_offerSubscriptionProcessService = A.Fake();
_serviceProviderDetails = new HashSet();
_identity = A.Fake();
- _identityService = A.Fake();
+ var identityService = A.Fake();
A.CallTo(() => _identity.IdentityId).Returns(Guid.NewGuid());
A.CallTo(() => _identity.IdentityTypeId).Returns(IdentityTypeId.COMPANY_USER);
A.CallTo(() => _identity.CompanyId).Returns(ExistingCompanyId);
- A.CallTo(() => _identityService.IdentityData).Returns(_identity);
+ A.CallTo(() => identityService.IdentityData).Returns(_identity);
A.CallTo(() => _portalRepositories.GetInstance()).Returns(_companyRepository);
+ A.CallTo(() => _portalRepositories.GetInstance()).Returns(_processStepRepository);
A.CallTo(() => _portalRepositories.GetInstance())
.Returns(_offerSubscriptionsRepository);
- _sut = new SubscriptionConfigurationBusinessLogic(_offerSubscriptionProcessService, _portalRepositories, _identityService);
+ _sut = new SubscriptionConfigurationBusinessLogic(_offerSubscriptionProcessService, _portalRepositories, identityService);
}
#region GetProcessStepsForSubscription
@@ -190,9 +192,9 @@ public async Task SetProviderCompanyDetailsAsync_EmptyProviderDetailsId_ReturnsE
{
// Arrange
SetupProviderCompanyDetails();
- var providerDetailData = new ProviderDetailData("https://www.service-url.com", "https://www.test.com");
+ var providerDetailData = new ProviderDetailData("https://www.service-url.com", "https://example.org/callback");
A.CallTo(() => _companyRepository.GetProviderCompanyDetailsExistsForUser(ExistingCompanyId))
- .Returns((Guid.Empty, null!));
+ .Returns((Guid.Empty, null!, null));
// Act
await _sut.SetProviderCompanyDetailsAsync(providerDetailData);
@@ -211,7 +213,7 @@ public async Task SetProviderCompanyDetailsAsync_WithNotExistingAndUrlNull_DoesN
SetupProviderCompanyDetails();
var providerDetailData = new ProviderDetailData(null, null);
A.CallTo(() => _companyRepository.GetProviderCompanyDetailsExistsForUser(ExistingCompanyId))
- .Returns((Guid.Empty, null!));
+ .Returns((Guid.Empty, null!, null));
// Act
await _sut.SetProviderCompanyDetailsAsync(providerDetailData);
@@ -230,9 +232,23 @@ public async Task SetProviderCompanyDetailsAsync_WithProviderDetailsAndNoUrl_Rem
// Arrange
SetupProviderCompanyDetails();
var providerCompanyId = Guid.NewGuid();
+ var process1Id = Guid.NewGuid();
+ var process2Id = Guid.NewGuid();
+ var processStep1Id = Guid.NewGuid();
+ var processStep2Id = Guid.NewGuid();
var providerDetailData = new ProviderDetailData(null, null);
A.CallTo(() => _companyRepository.GetProviderCompanyDetailsExistsForUser(ExistingCompanyId))
- .Returns((providerCompanyId, null!));
+ .Returns((providerCompanyId, null!, null));
+ A.CallTo(() => _companyRepository.GetOfferSubscriptionProcessesForCompanyId(providerCompanyId))
+ .Returns(new List
+ {
+ new(
+ new Process(process1Id, ProcessTypeId.OFFER_SUBSCRIPTION, Guid.NewGuid()),
+ Enumerable.Repeat(new ProcessStep(processStep1Id, ProcessStepTypeId.RETRIGGER_PROVIDER, ProcessStepStatusId.TODO, process1Id, DateTimeOffset.UtcNow), 1)),
+ new(
+ new Process(process2Id, ProcessTypeId.OFFER_SUBSCRIPTION, Guid.NewGuid()),
+ Enumerable.Repeat(new ProcessStep(processStep2Id, ProcessStepTypeId.AWAIT_START_AUTOSETUP, ProcessStepStatusId.TODO, process2Id, DateTimeOffset.UtcNow), 1))
+ }.ToAsyncEnumerable());
// Act
await _sut.SetProviderCompanyDetailsAsync(providerDetailData);
@@ -245,6 +261,44 @@ public async Task SetProviderCompanyDetailsAsync_WithProviderDetailsAndNoUrl_Rem
_serviceProviderDetails.Should().BeEmpty();
}
+ [Fact]
+ public async Task SetProviderCompanyDetailsAsync_WithCallbackUrlChanged_HandlesProcessSteps()
+ {
+ // Arrange
+ SetupProviderCompanyDetails();
+ var process1Id = Guid.NewGuid();
+ var process2Id = Guid.NewGuid();
+ var processStep1Id = Guid.NewGuid();
+ var processStep2Id = Guid.NewGuid();
+ var providerDetailData = new ProviderDetailData(null, null);
+ A.CallTo(() => _companyRepository.GetProviderCompanyDetailsExistsForUser(ExistingCompanyId))
+ .Returns((ExistingCompanyId, "https://example.org", "https://example.org/callback"));
+ A.CallTo(() => _companyRepository.GetOfferSubscriptionProcessesForCompanyId(ExistingCompanyId))
+ .Returns(new List
+ {
+ new(
+ new Process(process1Id, ProcessTypeId.OFFER_SUBSCRIPTION, Guid.NewGuid()),
+ Enumerable.Repeat(new ProcessStep(processStep1Id, ProcessStepTypeId.RETRIGGER_PROVIDER, ProcessStepStatusId.TODO, process1Id, DateTimeOffset.UtcNow), 1)),
+ new(
+ new Process(process2Id, ProcessTypeId.OFFER_SUBSCRIPTION, Guid.NewGuid()),
+ Enumerable.Repeat(new ProcessStep(processStep2Id, ProcessStepTypeId.AWAIT_START_AUTOSETUP, ProcessStepStatusId.TODO, process2Id, DateTimeOffset.UtcNow), 1))
+ }.ToAsyncEnumerable());
+
+ // Act
+ await _sut.SetProviderCompanyDetailsAsync(providerDetailData);
+
+ // Assert
+ A.CallTo(() => _companyRepository.RemoveProviderCompanyDetails(ExistingCompanyId)).MustHaveHappenedOnceExactly();
+ A.CallTo(() => _companyRepository.CreateProviderCompanyDetail(A._, A._, A>._)).MustNotHaveHappened();
+ A.CallTo(() => _companyRepository.AttachAndModifyProviderCompanyDetails(A._, A>._, A>._)).MustNotHaveHappened();
+ A.CallTo(() => _processStepRepository.AttachAndModifyProcessSteps(A? Initialize, Action Modify)>>._)).MustHaveHappenedOnceExactly();
+ A.CallTo(() => _processStepRepository.AttachAndModifyProcessSteps(A? Initialize, Action Modify)>>.That.Matches(x => x.Count() == 1 && x.Single().ProcessStepId == processStep1Id))).MustHaveHappenedOnceExactly();
+ A.CallTo(() => _processStepRepository.CreateProcessStepRange(A>._)).MustHaveHappenedOnceExactly();
+ A.CallTo(() => _processStepRepository.CreateProcessStepRange(A>.That.Matches(x => x.Count() == 1 && x.Single().ProcessStepTypeId == ProcessStepTypeId.AWAIT_START_AUTOSETUP))).MustHaveHappenedOnceExactly();
+ A.CallTo(() => _portalRepositories.SaveAsync()).MustHaveHappenedOnceExactly();
+ _serviceProviderDetails.Should().BeEmpty();
+ }
+
[Fact]
public async Task SetProviderCompanyDetailsAsync_WithServiceProviderDetailsId_ReturnsExpectedResult()
{
@@ -259,7 +313,7 @@ public async Task SetProviderCompanyDetailsAsync_WithServiceProviderDetailsId_Re
ProviderCompanyDetail? modifyDetail = null;
A.CallTo(() => _companyRepository.GetProviderCompanyDetailsExistsForUser(ExistingCompanyId))
- .Returns((detailsId, existingUrl));
+ .Returns((detailsId, existingUrl, null));
A.CallTo(() => _companyRepository.AttachAndModifyProviderCompanyDetails(A._, A>._, A>._))
.Invokes((Guid id, Action initialize, Action modifiy) =>
@@ -430,9 +484,9 @@ private void SetupProviderCompanyDetails()
.Returns<(ProviderDetailReturnData, bool)>(default);
A.CallTo(() => _companyRepository.GetProviderCompanyDetailsExistsForUser(A.That.Matches(x => x == ExistingCompanyId)))
- .Returns((Guid.NewGuid(), _fixture.Create()));
+ .Returns((Guid.NewGuid(), _fixture.Create(), "https://example.org/callback"));
A.CallTo(() => _companyRepository.GetProviderCompanyDetailsExistsForUser(A.That.Not.Matches(x => x == ExistingCompanyId)))
- .Returns((Guid.Empty, null!));
+ .Returns((Guid.Empty, null!, null));
}
#endregion