Skip to content

Commit

Permalink
fix(autoSetup): notification will be created directly after subscribi…
Browse files Browse the repository at this point in the history
…ng (#273)

* fix(autoSetup): notification will be created directly after subscribing
instead of creating the notification for an app subscription after
triggering the provider, the notification will directly be created when
subscribing to an offer
Refs: CPLP-3288
---------
Reviewed-by: Norbert Truchsess <[email protected]>
  • Loading branch information
Phil91 authored Oct 10, 2023
1 parent 0ad522e commit 79fd86f
Show file tree
Hide file tree
Showing 15 changed files with 152 additions and 179 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,12 @@
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

using Microsoft.Extensions.Options;
using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling;
using Org.Eclipse.TractusX.Portal.Backend.OfferProvider.Library.DependencyInjection;
using Org.Eclipse.TractusX.Portal.Backend.OfferProvider.Library.Models;
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.Enums;
using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library;
using System.Text.Json;

namespace Org.Eclipse.TractusX.Portal.Backend.OfferProvider.Library.BusinessLogic;

Expand All @@ -35,7 +32,6 @@ public class OfferProviderBusinessLogic : IOfferProviderBusinessLogic
private readonly IPortalRepositories _portalRepositories;
private readonly IOfferProviderService _offerProviderService;
private readonly IProvisioningManager _provisioningManager;
private readonly OfferProviderSettings _settings;

/// <summary>
/// Constructor.
Expand All @@ -47,13 +43,11 @@ public class OfferProviderBusinessLogic : IOfferProviderBusinessLogic
public OfferProviderBusinessLogic(
IPortalRepositories portalRepositories,
IOfferProviderService offerProviderService,
IProvisioningManager provisioningManager,
IOptions<OfferProviderSettings> options)
IProvisioningManager provisioningManager)
{
_portalRepositories = portalRepositories;
_offerProviderService = offerProviderService;
_provisioningManager = provisioningManager;
_settings = options.Value;
}

/// <inheritdoc />
Expand All @@ -77,7 +71,7 @@ public OfferProviderBusinessLogic(
new OfferThirdPartyAutoSetupCustomerData(
data.CompanyInformationData.OrganizationName,
data.CompanyInformationData.Country,
data.UserEmail),
data.CompanyInformationData.CompanyUserEmail),
new OfferThirdPartyAutoSetupPropertyData(
data.CompanyInformationData.BusinessPartnerNumber,
offerSubscriptionId,
Expand All @@ -88,15 +82,6 @@ await _offerProviderService
.ConfigureAwait(false);
}

var content = JsonSerializer.Serialize(new
{
AppName = data.OfferName,
data.OfferId,
RequestorCompanyName = data.CompanyInformationData.OrganizationName,
data.UserEmail,
AutoSetupExecuted = triggerProvider
});
await SendNotifications(data.OfferId, data.OfferTypeId, data.SalesManagerId, data.CompanyUserId, content).ConfigureAwait(false);
return (
new[] {
data.IsSingleInstance ?
Expand All @@ -107,56 +92,6 @@ await _offerProviderService
null);
}

private async Task SendNotifications(
Guid offerId,
OfferTypeId offerTypeId,
Guid? salesManagerId,
Guid companyUserId,
string notificationContent)
{
var serviceManagerRoles = _settings.ServiceManagerRoles;
var notificationRepository = _portalRepositories.GetInstance<INotificationRepository>();

var notificationTypeId = offerTypeId == OfferTypeId.SERVICE ? NotificationTypeId.SERVICE_REQUEST : NotificationTypeId.APP_SUBSCRIPTION_REQUEST;
if (salesManagerId.HasValue)
{
notificationRepository.CreateNotification(salesManagerId.Value, notificationTypeId, false,
notification =>
{
notification.CreatorUserId = companyUserId;
notification.Content = notificationContent;
});
}

var userRolesRepository = _portalRepositories.GetInstance<IUserRolesRepository>();
var roleData = await userRolesRepository
.GetUserRoleIdsUntrackedAsync(serviceManagerRoles)
.ToListAsync()
.ConfigureAwait(false);
if (roleData.Count < serviceManagerRoles.Sum(clientRoles => clientRoles.UserRoleNames.Count()))
{
throw new ConfigurationException($"invalid configuration, at least one of the configured roles does not exist in the database: {string.Join(", ", serviceManagerRoles.Select(clientRoles => $"client: {clientRoles.ClientId}, roles: [{string.Join(", ", clientRoles.UserRoleNames)}]"))}");
}

await foreach (var receiver in _portalRepositories.GetInstance<IUserRepository>().GetServiceProviderCompanyUserWithRoleIdAsync(offerId, roleData))
{
if (salesManagerId.HasValue && receiver == salesManagerId.Value)
{
continue;
}

notificationRepository.CreateNotification(
receiver,
notificationTypeId,
false,
notification =>
{
notification.CreatorUserId = companyUserId;
notification.Content = notificationContent;
});
}
}

/// <inheritdoc />
public async Task<(IEnumerable<ProcessStepTypeId>? nextStepTypeIds, ProcessStepStatusId stepStatusId, bool modified, string? processMessage)> TriggerProviderCallback(Guid offerSubscriptionId, CancellationToken cancellationToken)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ public async Task AddFavouriteAppForUserAsync(Guid appId)

/// <inheritdoc/>
public Task<Guid> AddOwnCompanyAppSubscriptionAsync(Guid appId, IEnumerable<OfferAgreementConsentData> offerAgreementConsentData) =>
_offerSubscriptionService.AddOfferSubscriptionAsync(appId, offerAgreementConsentData, OfferTypeId.APP, _settings.BasePortalAddress, _settings.SubscriptionManagerRoles);
_offerSubscriptionService.AddOfferSubscriptionAsync(appId, offerAgreementConsentData, OfferTypeId.APP, _settings.BasePortalAddress, _settings.SubscriptionManagerRoles, _settings.ServiceManagerRoles);

/// <inheritdoc/>
public Task TriggerActivateOfferSubscription(Guid subscriptionId) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,10 @@
using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Configuration;
using Org.Eclipse.TractusX.Portal.Backend.Offers.Library.Models;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities;

namespace Org.Eclipse.TractusX.Portal.Backend.Offers.Library.Service;

public interface IOfferSubscriptionService
{
Task<Guid> AddOfferSubscriptionAsync(Guid offerId, IEnumerable<OfferAgreementConsentData> offerAgreementConsentData, OfferTypeId offerTypeId, string basePortalAddress, IEnumerable<UserRoleConfig> notificationRecipients);
Task<Guid> AddOfferSubscriptionAsync(Guid offerId, IEnumerable<OfferAgreementConsentData> offerAgreementConsentData, OfferTypeId offerTypeId, string basePortalAddress, IEnumerable<UserRoleConfig> notificationRecipients, IEnumerable<UserRoleConfig> serviceManagerRoles);
}
70 changes: 65 additions & 5 deletions src/marketplace/Offers.Library/Service/OfferSubscriptionService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Identities;
using System.Collections.Immutable;
using System.Text.Json;

namespace Org.Eclipse.TractusX.Portal.Backend.Offers.Library.Service;

Expand All @@ -43,7 +44,7 @@ public class OfferSubscriptionService : IOfferSubscriptionService
/// </summary>
/// <param name="portalRepositories">Factory to access the repositories</param>
/// <param name="identityService">Access to the identity of the user</param>
/// <param name="mailingService">Mail service.</param>
/// <param name="roleBaseMailService">Mail service.</param>
public OfferSubscriptionService(
IPortalRepositories portalRepositories,
IIdentityService identityService,
Expand All @@ -55,10 +56,10 @@ public OfferSubscriptionService(
}

/// <inheritdoc />
public async Task<Guid> AddOfferSubscriptionAsync(Guid offerId, IEnumerable<OfferAgreementConsentData> offerAgreementConsentData, OfferTypeId offerTypeId, string basePortalAddress, IEnumerable<UserRoleConfig> notificationRecipients)
public async Task<Guid> AddOfferSubscriptionAsync(Guid offerId, IEnumerable<OfferAgreementConsentData> offerAgreementConsentData, OfferTypeId offerTypeId, string basePortalAddress, IEnumerable<UserRoleConfig> notificationRecipients, IEnumerable<UserRoleConfig> serviceManagerRoles)
{
var identity = _identityService.IdentityData;
var companyInformation = await ValidateCompanyInformationAsync(identity.CompanyId).ConfigureAwait(false);
var companyInformation = await ValidateCompanyInformationAsync(identity.CompanyId, identity.UserId).ConfigureAwait(false);
var offerProviderDetails = await ValidateOfferProviderDetailDataAsync(offerId, offerTypeId).ConfigureAwait(false);

if (offerProviderDetails.ProviderCompanyId == null)
Expand All @@ -77,6 +78,15 @@ public async Task<Guid> AddOfferSubscriptionAsync(Guid offerId, IEnumerable<Offe
CreateConsentsForSubscription(offerSubscription.Id, offerAgreementConsentData, companyInformation.CompanyId, identity.UserId);
await _portalRepositories.SaveAsync().ConfigureAwait(false);

var content = JsonSerializer.Serialize(new
{
AppName = offerProviderDetails.OfferName,
OfferId = offerId,
RequesterCompanyName = companyInformation.OrganizationName,
UserEmail = companyInformation.CompanyUserEmail,
AutoSetupExecuted = !string.IsNullOrWhiteSpace(offerProviderDetails.AutoSetupUrl) && !offerProviderDetails.IsSingleInstance
});
await SendNotifications(offerId, offerTypeId, offerProviderDetails.SalesManagerId, identity.UserId, content, serviceManagerRoles).ConfigureAwait(false);
await _roleBaseMailService.RoleBaseSendMail(
notificationRecipients,
new[]
Expand All @@ -102,6 +112,56 @@ private void CreateProcessSteps(OfferSubscription offerSubscription)
processStepRepository.CreateProcessStepRange(new (ProcessStepTypeId, ProcessStepStatusId, Guid)[] { (ProcessStepTypeId.TRIGGER_PROVIDER, ProcessStepStatusId.TODO, process.Id) });
}

private async Task SendNotifications(
Guid offerId,
OfferTypeId offerTypeId,
Guid? salesManagerId,
Guid companyUserId,
string notificationContent,
IEnumerable<UserRoleConfig> serviceManagerRoles)
{
var notificationRepository = _portalRepositories.GetInstance<INotificationRepository>();

var notificationTypeId = offerTypeId == OfferTypeId.SERVICE ? NotificationTypeId.SERVICE_REQUEST : NotificationTypeId.APP_SUBSCRIPTION_REQUEST;
if (salesManagerId.HasValue)
{
notificationRepository.CreateNotification(salesManagerId.Value, notificationTypeId, false,
notification =>
{
notification.CreatorUserId = companyUserId;
notification.Content = notificationContent;
});
}

var userRolesRepository = _portalRepositories.GetInstance<IUserRolesRepository>();
var roleData = await userRolesRepository
.GetUserRoleIdsUntrackedAsync(serviceManagerRoles)
.ToListAsync()
.ConfigureAwait(false);
if (roleData.Count < serviceManagerRoles.Sum(clientRoles => clientRoles.UserRoleNames.Count()))
{
throw new ConfigurationException($"invalid configuration, at least one of the configured roles does not exist in the database: {string.Join(", ", serviceManagerRoles.Select(clientRoles => $"client: {clientRoles.ClientId}, roles: [{string.Join(", ", clientRoles.UserRoleNames)}]"))}");
}

await foreach (var receiver in _portalRepositories.GetInstance<IUserRepository>().GetServiceProviderCompanyUserWithRoleIdAsync(offerId, roleData))
{
if (salesManagerId.HasValue && receiver == salesManagerId.Value)
{
continue;
}

notificationRepository.CreateNotification(
receiver,
notificationTypeId,
false,
notification =>
{
notification.CreatorUserId = companyUserId;
notification.Content = notificationContent;
});
}
}

private async Task<OfferProviderDetailsData> ValidateOfferProviderDetailDataAsync(Guid offerId, OfferTypeId offerTypeId)
{
var offerProviderDetails = await _portalRepositories.GetInstance<IOfferRepository>()
Expand Down Expand Up @@ -133,10 +193,10 @@ private async Task ValidateConsent(IEnumerable<OfferAgreementConsentData> offerA
}
}

private async Task<CompanyInformationData> ValidateCompanyInformationAsync(Guid companyId)
private async Task<CompanyInformationData> ValidateCompanyInformationAsync(Guid companyId, Guid companyUserId)
{
var companyInformation = await _portalRepositories.GetInstance<ICompanyRepository>()
.GetOwnCompanyInformationAsync(companyId).ConfigureAwait(false);
.GetOwnCompanyInformationAsync(companyId, companyUserId).ConfigureAwait(false);
if (companyInformation == null)
{
throw new ControllerArgumentException($"Company {companyId} does not exist", nameof(companyId));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public ServiceBusinessLogic(

/// <inheritdoc />
public Task<Guid> AddServiceSubscription(Guid serviceId, IEnumerable<OfferAgreementConsentData> offerAgreementConsentData) =>
_offerSubscriptionService.AddOfferSubscriptionAsync(serviceId, offerAgreementConsentData, OfferTypeId.SERVICE, _settings.BasePortalAddress, _settings.SubscriptionManagerRoles);
_offerSubscriptionService.AddOfferSubscriptionAsync(serviceId, offerAgreementConsentData, OfferTypeId.SERVICE, _settings.BasePortalAddress, _settings.SubscriptionManagerRoles, _settings.ServiceManagerRoles);

/// <inheritdoc />
public async Task<ServiceDetailResponse> GetServiceDetailsAsync(Guid serviceId, string lang)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ public record CompanyInformationData(
Guid CompanyId,
string OrganizationName,
string? Country,
string? BusinessPartnerNumber);
string? BusinessPartnerNumber,
string? CompanyUserEmail);
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ public record TriggerProviderInformation(
string? OfferName,
string? AutoSetupUrl,
CompanyInformationData CompanyInformationData,
string? UserEmail,
OfferTypeId OfferTypeId,
Guid? SalesManagerId,
Guid CompanyUserId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,15 +281,16 @@ public IAsyncEnumerable<CompanyRoleConsentData> GetCompanyRoleAndConsentAgreemen
true
)).SingleOrDefaultAsync();

public Task<CompanyInformationData?> GetOwnCompanyInformationAsync(Guid companyId) =>
public Task<CompanyInformationData?> GetOwnCompanyInformationAsync(Guid companyId, Guid companyUserId) =>
_context.Companies
.AsNoTracking()
.Where(c => c.Id == companyId)
.Select(user => new CompanyInformationData(
user.Id,
user.Name,
user.Address!.CountryAlpha2Code,
user.BusinessPartnerNumber
.Select(company => new CompanyInformationData(
company.Id,
company.Name,
company.Address!.CountryAlpha2Code,
company.BusinessPartnerNumber,
company.Identities.Where(x => x.Id == companyUserId && x.IdentityTypeId == IdentityTypeId.COMPANY_USER).Select(x => x.CompanyUser!.Email).SingleOrDefault()
))
.SingleOrDefaultAsync();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ public interface ICompanyRepository
/// <returns>Returns the CompanyStatus Data</returns>
Task<(bool IsActive, bool IsValid)> GetCompanyStatusDataAsync(Guid companyId);

Task<CompanyInformationData?> GetOwnCompanyInformationAsync(Guid companyId);
Task<CompanyInformationData?> GetOwnCompanyInformationAsync(Guid companyId, Guid companyUserId);
IAsyncEnumerable<CompanyRoleId> GetOwnCompanyRolesAsync(Guid companyId);

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -362,9 +362,9 @@ public Task<Guid> GetOfferSubscriptionDataForProcessIdAsync(Guid processId) =>
x.RequesterCompany!.Id,
x.RequesterCompany.Name,
x.RequesterCompany.Address!.CountryAlpha2Code,
x.RequesterCompany.BusinessPartnerNumber
x.RequesterCompany.BusinessPartnerNumber,
x.Email
),
x.Email,
x.OfferTypeId,
x.SalesManagerId,
x.CompanyUserId,
Expand Down
Loading

0 comments on commit 79fd86f

Please sign in to comment.