Skip to content

Commit

Permalink
feat(sd): add process steps for sd creation (#1189)
Browse files Browse the repository at this point in the history
* feat(sd): add process steps for sd creation + retrigger
* update framework minor version
* add and adjust unit tests
Refs: #1182
---------
Co-authored-by: Norbert Truchsess <[email protected]>
  • Loading branch information
Phil91 committed Jan 31, 2025
1 parent a676ac4 commit 6371f0e
Show file tree
Hide file tree
Showing 50 changed files with 11,064 additions and 96 deletions.
66 changes: 66 additions & 0 deletions docs/api/administration-service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,37 @@ paths:
description: Internal Server Error
'401':
description: The User is unauthorized
/api/administration/companydata/retrigger-self-description-response:
post:
tags:
- CompanyData
summary: 'Retriggers the process to create the missing self description documents (Authorization required - Roles: approve_new_partner)'
parameters:
- name: processId
in: path
required: true
schema:
type: string
format: uuid
responses:
'204':
description: Empty response on success.
'400':
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: No Process found for the processId
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal Server Error
'401':
description: The User is unauthorized
/api/administration/Connectors:
get:
tags:
Expand Down Expand Up @@ -1178,6 +1209,37 @@ paths:
description: Internal Server Error
'401':
description: The User is unauthorized
/api/administration/Connectors/retrigger-self-description-response:
post:
tags:
- Connectors
summary: 'Retriggers the process to create the missing self description response documents (Authorization required - Roles: approve_new_partner)'
parameters:
- name: processId
in: path
required: true
schema:
type: string
format: uuid
responses:
'204':
description: Empty response on success.
'400':
description: Bad Request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: No Process found for the processId
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal Server Error
'401':
description: The User is unauthorized
'/api/administration/Documents/{documentId}':
get:
tags:
Expand Down Expand Up @@ -7646,6 +7708,10 @@ components:
- SELF_DESCRIPTION_COMPANY_CREATION
- RETRIGGER_SELF_DESCRIPTION_CONNECTOR_CREATION
- RETRIGGER_SELF_DESCRIPTION_COMPANY_CREATION
- AWAIT_SELF_DESCRIPTION_CONNECTOR_RESPONSE
- AWAIT_SELF_DESCRIPTION_COMPANY_RESPONSE
- RETRIGGER_AWAIT_SELF_DESCRIPTION_CONNECTOR_RESPONSE
- RETRIGGER_AWAIT_SELF_DESCRIPTION_COMPANY_RESPONSE
type: string
ProviderDetailData:
type: object
Expand Down
4 changes: 4 additions & 0 deletions docs/api/apps-service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3700,6 +3700,10 @@ components:
- SELF_DESCRIPTION_COMPANY_CREATION
- RETRIGGER_SELF_DESCRIPTION_CONNECTOR_CREATION
- RETRIGGER_SELF_DESCRIPTION_COMPANY_CREATION
- AWAIT_SELF_DESCRIPTION_CONNECTOR_RESPONSE
- AWAIT_SELF_DESCRIPTION_COMPANY_RESPONSE
- RETRIGGER_AWAIT_SELF_DESCRIPTION_CONNECTOR_RESPONSE
- RETRIGGER_AWAIT_SELF_DESCRIPTION_COMPANY_RESPONSE
type: string
SubscriberSubscriptionDetailData:
type: object
Expand Down
4 changes: 4 additions & 0 deletions docs/api/services-service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2271,6 +2271,10 @@ components:
- SELF_DESCRIPTION_COMPANY_CREATION
- RETRIGGER_SELF_DESCRIPTION_CONNECTOR_CREATION
- RETRIGGER_SELF_DESCRIPTION_COMPANY_CREATION
- AWAIT_SELF_DESCRIPTION_CONNECTOR_RESPONSE
- AWAIT_SELF_DESCRIPTION_COMPANY_RESPONSE
- RETRIGGER_AWAIT_SELF_DESCRIPTION_CONNECTOR_RESPONSE
- RETRIGGER_AWAIT_SELF_DESCRIPTION_COMPANY_RESPONSE
type: string
ProviderSubscriptionDetailData:
type: object
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -458,17 +458,21 @@ public async Task TriggerSelfDescriptionCreation()
await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
}

public async Task RetriggerSelfDescriptionCreation(Guid processId)
public Task RetriggerSelfDescriptionCreation(Guid processId) => RetriggerSelfDescriptionCompanyCreation(processId, ProcessStepTypeId.RETRIGGER_SELF_DESCRIPTION_COMPANY_CREATION);

public Task RetriggerSelfDescriptionResponseCreation(Guid processId) => RetriggerSelfDescriptionCompanyCreation(processId, ProcessStepTypeId.RETRIGGER_AWAIT_SELF_DESCRIPTION_COMPANY_RESPONSE);

private async Task RetriggerSelfDescriptionCompanyCreation(Guid processId, ProcessStepTypeId stepToTrigger)
{
const ProcessStepTypeId NextStep = ProcessStepTypeId.SELF_DESCRIPTION_COMPANY_CREATION;
const ProcessStepTypeId StepToTrigger = ProcessStepTypeId.RETRIGGER_SELF_DESCRIPTION_COMPANY_CREATION;
var (validProcessId, processData) = await portalRepositories.GetInstance<IPortalProcessStepRepository>().IsValidProcess(processId, ProcessTypeId.SELF_DESCRIPTION_CREATION, Enumerable.Repeat(StepToTrigger, 1)).ConfigureAwait(ConfigureAwaitOptions.None);

var (validProcessId, processData) = await portalRepositories.GetInstance<IPortalProcessStepRepository>().IsValidProcess(processId, ProcessTypeId.SELF_DESCRIPTION_CREATION, Enumerable.Repeat(stepToTrigger, 1)).ConfigureAwait(ConfigureAwaitOptions.None);
if (!validProcessId)
{
throw NotFoundException.Create(AdministrationCompanyDataErrors.COMPANY_DATA_NOT_PROCESSID_NOT_EXIST, new ErrorParameter[] { new(nameof(processId), processId.ToString()) });
}

var context = processData.CreateManualProcessData(StepToTrigger, portalRepositories, () => $"processId {processId}");
var context = processData.CreateManualProcessData(stepToTrigger, portalRepositories, () => $"processId {processId}");

context.ScheduleProcessSteps(Enumerable.Repeat(NextStep, 1));
context.FinalizeProcessStep();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -491,17 +491,20 @@ public async Task TriggerSelfDescriptionCreation()
await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
}

public async Task RetriggerSelfDescriptionCreation(Guid processId)
public Task RetriggerSelfDescriptionCreation(Guid processId) => RetriggerSelfDescriptionConnectorCreation(processId, ProcessStepTypeId.RETRIGGER_SELF_DESCRIPTION_CONNECTOR_CREATION);

public Task RetriggerSelfDescriptionResponseCreation(Guid processId) => RetriggerSelfDescriptionConnectorCreation(processId, ProcessStepTypeId.RETRIGGER_AWAIT_SELF_DESCRIPTION_CONNECTOR_RESPONSE);

private async Task RetriggerSelfDescriptionConnectorCreation(Guid processId, ProcessStepTypeId stepToTrigger)
{
const ProcessStepTypeId NextStep = ProcessStepTypeId.SELF_DESCRIPTION_CONNECTOR_CREATION;
const ProcessStepTypeId StepToTrigger = ProcessStepTypeId.RETRIGGER_SELF_DESCRIPTION_CONNECTOR_CREATION;
var (validProcessId, processData) = await portalRepositories.GetInstance<IPortalProcessStepRepository>().IsValidProcess(processId, ProcessTypeId.SELF_DESCRIPTION_CREATION, Enumerable.Repeat(StepToTrigger, 1)).ConfigureAwait(ConfigureAwaitOptions.None);
var (validProcessId, processData) = await portalRepositories.GetInstance<IPortalProcessStepRepository>().IsValidProcess(processId, ProcessTypeId.SELF_DESCRIPTION_CREATION, Enumerable.Repeat(stepToTrigger, 1)).ConfigureAwait(ConfigureAwaitOptions.None);
if (!validProcessId)
{
throw new NotFoundException($"process {processId} does not exist");
}

var context = processData.CreateManualProcessData(StepToTrigger, portalRepositories, () => $"processId {processId}");
var context = processData.CreateManualProcessData(stepToTrigger, portalRepositories, () => $"processId {processId}");

context.ScheduleProcessSteps(Enumerable.Repeat(NextStep, 1));
context.FinalizeProcessStep();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,6 @@ public interface ICompanyDataBusinessLogic
Task<DimUrlsResponse> GetDimServiceUrls();
Task<Pagination.Response<CompanyMissingSdDocumentData>> GetCompaniesWithMissingSdDocument(int page, int size);
Task RetriggerSelfDescriptionCreation(Guid processId);
Task RetriggerSelfDescriptionResponseCreation(Guid processId);
Task TriggerSelfDescriptionCreation();
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,5 @@ public interface IConnectorsBusinessLogic
Task<Pagination.Response<ConnectorMissingSdDocumentData>> GetConnectorsWithMissingSdDocument(int page, int size);
Task TriggerSelfDescriptionCreation();
Task RetriggerSelfDescriptionCreation(Guid processId);
Task RetriggerSelfDescriptionResponseCreation(Guid processId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling;
using Org.Eclipse.TractusX.Portal.Backend.Framework.Identity;
using Org.Eclipse.TractusX.Portal.Backend.Framework.IO;
using Org.Eclipse.TractusX.Portal.Backend.Framework.Processes.Library.Enums;
using Org.Eclipse.TractusX.Portal.Backend.Framework.Processes.Library.Extensions;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Models;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories;
Expand All @@ -30,30 +32,26 @@

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;

/// <inheritdoc />
public async Task<ProviderDetailReturnData> GetProviderCompanyDetailsAsync()
{
var companyId = _identityData.CompanyId;
var result = await _portalRepositories.GetInstance<ICompanyRepository>()
var result = await portalRepositories.GetInstance<ICompanyRepository>()
.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()) });
Expand All @@ -78,7 +76,7 @@ public Task SetProviderCompanyDetailsAsync(ProviderDetailData data)

private async Task SetOfferProviderCompanyDetailsInternalAsync(ProviderDetailData data, Guid companyId)
{
var companyRepository = _portalRepositories.GetInstance<ICompanyRepository>();
var companyRepository = portalRepositories.GetInstance<ICompanyRepository>();
var providerDetailData = await companyRepository
.GetProviderCompanyDetailsExistsForUser(companyId)
.ConfigureAwait(ConfigureAwaitOptions.None);
Expand All @@ -92,9 +90,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;
});
Expand All @@ -106,9 +109,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));
}
}

Expand All @@ -129,11 +158,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;
});
}
Expand All @@ -158,18 +183,17 @@ public Task RetriggerProviderCallback(Guid offerSubscriptionId) =>
public Task RetriggerCreateDimTechnicalUser(Guid offerSubscriptionId) =>
TriggerProcessStep(offerSubscriptionId, ProcessStepTypeId.RETRIGGER_OFFERSUBSCRIPTION_CREATE_DIM_TECHNICAL_USER, true);

/// <inheritdoc />
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);
}

/// <inheritdoc />
public IAsyncEnumerable<ProcessStepData> GetProcessStepsForSubscription(Guid offerSubscriptionId) =>
_portalRepositories.GetInstance<IOfferSubscriptionsRepository>().GetProcessStepsForSubscription(offerSubscriptionId);
portalRepositories.GetInstance<IOfferSubscriptionsRepository>().GetProcessStepsForSubscription(offerSubscriptionId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -385,4 +385,24 @@ public async Task<NoContentResult> RetriggerSelfDescriptionProcess([FromRoute] G
await logic.RetriggerSelfDescriptionCreation(processId).ConfigureAwait(false);
return NoContent();
}

/// <summary>
/// Retriggers the process to create the missing self description documents
/// </summary>
/// <returns>NoContent</returns>
/// Example: POST: /api/administration/companyData/trigger-self-description-response/{processId}
/// <response code="204">Empty response on success.</response>
/// <response code="404">No Process found for the processId</response>
[HttpPost]
[Authorize(Roles = "approve_new_partner")]
[Authorize(Policy = PolicyTypes.CompanyUser)]
[Route("retrigger-self-description-response")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)]
public async Task<NoContentResult> RetriggerSelfDescriptionResponseProcess([FromRoute] Guid processId)
{
await logic.RetriggerSelfDescriptionResponseCreation(processId).ConfigureAwait(false);
return NoContent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -307,4 +307,24 @@ public async Task<NoContentResult> RetriggerSelfDescriptionProcess([FromRoute] G
await logic.RetriggerSelfDescriptionCreation(processId).ConfigureAwait(false);
return NoContent();
}

/// <summary>
/// Retriggers the process to create the missing self description response documents
/// </summary>
/// <returns>NoContent</returns>
/// Example: POST: /api/administration/connectors/retrigger-self-description-response/{processId}
/// <response code="204">Empty response on success.</response>
/// <response code="404">No Process found for the processId</response>
[HttpPost]
[Authorize(Roles = "approve_new_partner")]
[Authorize(Policy = PolicyTypes.CompanyUser)]
[Route("retrigger-self-description-response")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status404NotFound)]
public async Task<NoContentResult> RetriggerSelfDescriptionResponseProcess([FromRoute] Guid processId)
{
await logic.RetriggerSelfDescriptionResponseCreation(processId).ConfigureAwait(false);
return NoContent();
}
}
Loading

0 comments on commit 6371f0e

Please sign in to comment.