Skip to content

Commit

Permalink
possible to order notification for org
Browse files Browse the repository at this point in the history
  • Loading branch information
acn-sbuad committed Apr 24, 2024
1 parent 0b96880 commit c7e2b01
Show file tree
Hide file tree
Showing 39 changed files with 251 additions and 144 deletions.
17 changes: 17 additions & 0 deletions src/Altinn.Notifications.Core/Integrations/IRegisterClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Altinn.Notifications.Core.Models.ContactPoints;

namespace Altinn.Notifications.Core.Integrations
{
/// <summary>
/// Interface describing a client for the register service
/// </summary>
public interface IRegisterClient
{
/// <summary>
/// Retrieves contact points for a list of organizations
/// </summary>
/// <param name="organizationNumbers">A list of organization numbers to look up contact points for</param>
/// <returns>A list of <see cref="OrganizationContactPoints"/> for the provided organizations</returns>
public Task<List<OrganizationContactPoints>> GeOrganizationContactPoints(List<string> organizationNumbers);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace Altinn.Notifications.Core.Models.ContactPoints;

/// <summary>
/// Class describing the contact points for an organization
/// </summary>
public class OrganizationContactPoints
{
/// <summary>
/// Gets or sets the organization number for the organization
/// </summary>
public string OrganizationNumber { get; set; } = string.Empty;

/// <summary>
/// Gets or sets a list of official mobile numbers
/// </summary>
public List<string> MobileNumberList { get; set; } = [];

/// <summary>
/// Gets or sets a list of official email addresses
/// </summary>
public List<string> EmailList { get; set; } = [];
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class MonthlyNotificationMetrics
public int Year { get; set; }

/// <summary>
/// A list of metrics per organisation
/// A list of metrics per organization
/// </summary>
public List<MetricsForOrg> Metrics { get; set; } = [];
}
8 changes: 4 additions & 4 deletions src/Altinn.Notifications.Core/Models/Recipient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ namespace Altinn.Notifications.Core.Models;
public class Recipient
{
/// <summary>
/// Gets the recipient's organisation number
/// Gets the recipient's organization number
/// </summary>
public string? OrganisationNumber { get; set; } = null;
public string? OrganizationNumber { get; set; } = null;

/// <summary>
/// Gets the recipient's national identity number
Expand All @@ -32,9 +32,9 @@ public class Recipient
/// <summary>
/// Initializes a new instance of the <see cref="Recipient"/> class.
/// </summary>
public Recipient(List<IAddressPoint> addressInfo, string? organisationNumber = null, string? nationalIdentityNumber = null)
public Recipient(List<IAddressPoint> addressInfo, string? organizationNumber = null, string? nationalIdentityNumber = null)
{
OrganisationNumber = organisationNumber;
OrganizationNumber = organizationNumber;
NationalIdentityNumber = nationalIdentityNumber;
AddressInfo = addressInfo;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ namespace Altinn.Notifications.Core.Models.Recipients;
public class EmailRecipient
{
/// <summary>
/// Gets or sets the recipient's organisation number
/// Gets or sets the recipient's organization number
/// </summary>
public string? OrganisationNumber { get; set; } = null;
public string? OrganizationNumber { get; set; } = null;

/// <summary>
/// Gets or sets the recipient's national identity number
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ namespace Altinn.Notifications.Core.Models.Recipients;
public class SmsRecipient
{
/// <summary>
/// Gets or sets the recipient's organisation number
/// Gets or sets the recipient's organization number
/// </summary>
public string? OrganisationNumber { get; set; } = null;
public string? OrganizationNumber { get; set; } = null;

/// <summary>
/// Gets or sets the recipient's national identity number
Expand Down
90 changes: 52 additions & 38 deletions src/Altinn.Notifications.Core/Services/ContactPointService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ namespace Altinn.Notifications.Core.Services
public class ContactPointService : IContactPointService
{
private readonly IProfileClient _profileClient;
private readonly IRegisterClient _registerClient;

/// <summary>
/// Initializes a new instance of the <see cref="ContactPointService"/> class.
/// </summary>
public ContactPointService(IProfileClient profile)
public ContactPointService(IProfileClient profile, IRegisterClient register)
{
_profileClient = profile;
_registerClient = register;
}

/// <inheritdoc/>
Expand All @@ -30,6 +32,11 @@ await AugmentRecipients(
{
recipient.AddressInfo.Add(new EmailAddressPoint(userContactPoints.Email));
return recipient;
},
(recipient, orgContactPoints) =>
{
recipient.AddressInfo.AddRange(orgContactPoints.EmailList.Select(e => new EmailAddressPoint(e)).ToList());
return recipient;
});
}

Expand All @@ -42,20 +49,28 @@ await AugmentRecipients(
{
recipient.AddressInfo.Add(new SmsAddressPoint(userContactPoints.MobileNumber));
return recipient;
},
(recipient, orgContactPoints) =>
{
recipient.AddressInfo.AddRange(orgContactPoints.MobileNumberList.Select(m => new SmsAddressPoint(m)).ToList());
return recipient;
});
}

/// <inheritdoc/>
public async Task<List<UserContactPointAvailability>> GetContactPointAvailability(List<Recipient> recipients)
{
return await LookupContactPointAvailability(recipients);
}

private async Task<List<Recipient>> AugmentRecipients(List<Recipient> recipients, Func<Recipient, UserContactPoints, Recipient> createContactPoint)
private async Task<List<Recipient>> AugmentRecipients(
List<Recipient> recipients,
Func<Recipient, UserContactPoints, Recipient> createUserContactPoint,
Func<Recipient, OrganizationContactPoints, Recipient> createOrgContactPoint)
{
List<Recipient> augmentedRecipients = [];

List<UserContactPoints> userContactPointsList = await LookupContactPoints(recipients);
var userLookupTask = LookupUserContactPoints(recipients);
var orgLookupTask = LookupOrganizationContactPoints(recipients);
await Task.WhenAll(userLookupTask, orgLookupTask);

List<UserContactPoints> userContactPointsList = userLookupTask.Result;
List<OrganizationContactPoints> organizationContactPointList = orgLookupTask.Result;

foreach (Recipient recipient in recipients)
{
if (!string.IsNullOrEmpty(recipient.NationalIdentityNumber))
Expand All @@ -66,51 +81,50 @@ private async Task<List<Recipient>> AugmentRecipients(List<Recipient> recipients
if (userContactPoints != null)
{
recipient.IsReserved = userContactPoints.IsReserved;
augmentedRecipients.Add(createContactPoint(recipient, userContactPoints));
augmentedRecipients.Add(createUserContactPoint(recipient, userContactPoints));
}
}
else if (!string.IsNullOrEmpty(recipient.OrganizationNumber))
{
OrganizationContactPoints? organizationContactPoints = organizationContactPointList!
.Find(o => o.OrganizationNumber == recipient.OrganizationNumber);

if (organizationContactPoints != null)
{
augmentedRecipients.Add(createOrgContactPoint(recipient, organizationContactPoints));
}
}
}

return augmentedRecipients;
}

private async Task<List<UserContactPoints>> LookupContactPoints(List<Recipient> recipients)
private async Task<List<UserContactPoints>> LookupUserContactPoints(List<Recipient> recipients)
{
List<UserContactPoints> userContactPoints = new();
List<string> nins = recipients
.Where(r => !string.IsNullOrEmpty(r.NationalIdentityNumber))
.Select(r => r.NationalIdentityNumber!)
.ToList();

Task<List<UserContactPoints>> ninLookupTask = nins.Count > 0
? _profileClient.GetUserContactPoints(nins)
: Task.FromResult(new List<UserContactPoints>());

await Task.WhenAll(ninLookupTask);

userContactPoints.AddRange(ninLookupTask.Result);

return userContactPoints;
// TODO: ensure all mobile numbers have country code before returning

Check warning on line 109 in src/Altinn.Notifications.Core/Services/ContactPointService.cs

View workflow job for this annotation

GitHub Actions / Build, test & analyze

Complete the task associated to this 'TODO' comment. (https://rules.sonarsource.com/csharp/RSPEC-1135)

Check warning on line 109 in src/Altinn.Notifications.Core/Services/ContactPointService.cs

View workflow job for this annotation

GitHub Actions / Build, test & analyze

Complete the task associated to this 'TODO' comment. (https://rules.sonarsource.com/csharp/RSPEC-1135)

Check warning on line 109 in src/Altinn.Notifications.Core/Services/ContactPointService.cs

View workflow job for this annotation

GitHub Actions / Build, test & analyze

Complete the task associated to this 'TODO' comment. (https://rules.sonarsource.com/csharp/RSPEC-1135)
return nins.Count > 0
? await _profileClient.GetUserContactPoints(nins)
: new List<UserContactPoints>();
}

private async Task<List<UserContactPointAvailability>> LookupContactPointAvailability(List<Recipient> recipients)
private async Task<List<OrganizationContactPoints>> LookupOrganizationContactPoints(List<Recipient> recipients)
{
List<UserContactPointAvailability> contactPointAvailabilityList = new();

List<string> nins = recipients
.Where(r => !string.IsNullOrEmpty(r.NationalIdentityNumber))
.Select(r => r.NationalIdentityNumber!)
.ToList();

Task<List<UserContactPointAvailability>> ninLookupTask = nins.Count > 0
? _profileClient.GetUserContactPointAvailabilities(nins)
: Task.FromResult(new List<UserContactPointAvailability>());

await Task.WhenAll(ninLookupTask);

contactPointAvailabilityList.AddRange(ninLookupTask.Result);

return contactPointAvailabilityList;
/* the output from this function should include an AUHTORIZED list of user registered contact points if notification has a service affiliation
will require the extension of the OrganizationContactPoints class */
List<string> orgNos = recipients
.Where(r => !string.IsNullOrEmpty(r.OrganizationNumber))
.Select(r => r.OrganizationNumber!)
.ToList();

// TODO: ensure all mobile numbers have country code before returning

Check warning on line 124 in src/Altinn.Notifications.Core/Services/ContactPointService.cs

View workflow job for this annotation

GitHub Actions / Build, test & analyze

Complete the task associated to this 'TODO' comment. (https://rules.sonarsource.com/csharp/RSPEC-1135)

Check warning on line 124 in src/Altinn.Notifications.Core/Services/ContactPointService.cs

View workflow job for this annotation

GitHub Actions / Build, test & analyze

Complete the task associated to this 'TODO' comment. (https://rules.sonarsource.com/csharp/RSPEC-1135)

Check warning on line 124 in src/Altinn.Notifications.Core/Services/ContactPointService.cs

View workflow job for this annotation

GitHub Actions / Build, test & analyze

Complete the task associated to this 'TODO' comment. (https://rules.sonarsource.com/csharp/RSPEC-1135)
return orgNos.Count > 0
? await _registerClient.GeOrganizationContactPoints(orgNos)
: new List<OrganizationContactPoints>();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public async Task CreateNotification(Guid orderId, DateTime requestedSendTime, R

EmailRecipient emailRecipient = new()
{
OrganisationNumber = recipient.OrganisationNumber,
OrganizationNumber = recipient.OrganizationNumber,
NationalIdentityNumber = recipient.NationalIdentityNumber,
ToAddress = addressPoint?.EmailAddress ?? string.Empty,
IsReserved = recipient.IsReserved
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public async Task ProcessOrderRetry(NotificationOrder order)

if (!emailRecipients.Exists(er =>
er.NationalIdentityNumber == recipient.NationalIdentityNumber
&& er.OrganisationNumber == recipient.OrganisationNumber
&& er.OrganizationNumber == recipient.OrganizationNumber
&& er.ToAddress == addressPoint?.EmailAddress))
{
await _emailService.CreateNotification(order.Id, order.RequestedSendTime, recipient, order.IgnoreReservation);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Altinn.Notifications.Core.Models;
using Altinn.Notifications.Core.Models.ContactPoints;

namespace Altinn.Notifications.Core.Services.Interfaces
{
Expand All @@ -9,26 +8,19 @@ namespace Altinn.Notifications.Core.Services.Interfaces
public interface IContactPointService
{
/// <summary>
/// Looks up and adds the email contact points for recipients based on their national identity number or organisation number
/// Looks up and adds the email contact points for recipients based on their national identity number or organization number
/// </summary>
/// <param name="recipients">List of recipients to retrieve contact points for</param>
/// <returns>The list of recipients augumented with email address points where available</returns>
/// <remarks>Implementation alters the recipient reference object directly</remarks>
public Task AddEmailContactPoints(List<Recipient> recipients);

/// <summary>
/// Looks up and adds the SMS contact points for recipients based on their national identity number or organisation number
/// Looks up and adds the SMS contact points for recipients based on their national identity number or organization number
/// </summary>
/// <param name="recipients">List of recipients to retrieve contact points for</param>
/// <returns>The list of recipients augumented with SMS address points where available</returns>
/// <remarks>Implementation alters the recipient reference object directly</remarks>
public Task AddSmsContactPoints(List<Recipient> recipients);

/// <summary>
/// Retrieves the availabililty of contact points for the provided recipient based on their national identity number or organisation number
/// </summary>
/// <param name="recipients">List of recipients to check contact point availability for</param>
/// <returns>The list of recipients with contact point availability details</returns>
public Task<List<UserContactPointAvailability>> GetContactPointAvailability(List<Recipient> recipients);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public async Task<NotificationOrderRequestResponse> RegisterNotificationOrder(No
.Where(r => channel == NotificationChannel.Email ?
!r.AddressInfo.Exists(ap => ap.AddressType == AddressType.Email) :
!r.AddressInfo.Exists(ap => ap.AddressType == AddressType.Sms))
.Select(r => r.OrganisationNumber ?? r.NationalIdentityNumber!)
.Select(r => r.OrganizationNumber ?? r.NationalIdentityNumber!)
.Except(isReserved)
.ToList()
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public async Task CreateNotification(Guid orderId, DateTime requestedSendTime, R

SmsRecipient smsRecipient = new()
{
OrganisationNumber = recipient.OrganisationNumber,
OrganizationNumber = recipient.OrganizationNumber,
NationalIdentityNumber = recipient.NationalIdentityNumber,
MobileNumber = addressPoint?.MobileNumber ?? string.Empty,
IsReserved = recipient.IsReserved
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public async Task ProcessOrderRetry(NotificationOrder order)

if (!smsRecipients.Exists(sr =>
sr.NationalIdentityNumber == recipient.NationalIdentityNumber
&& sr.OrganisationNumber == recipient.OrganisationNumber
&& sr.OrganizationNumber == recipient.OrganizationNumber
&& sr.MobileNumber == addressPoint?.MobileNumber))
{
await _smsService.CreateNotification(order.Id, order.RequestedSendTime, recipient, smsCount);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@
public class PlatformSettings
{
/// <summary>
/// Gets or sets the url for the API profile endpoint
/// Gets or sets the url for the profile API
/// </summary>
public string ApiProfileEndpoint { get; set; } = string.Empty;

/// <summary>
/// Gets or sets the url for the register API
/// </summary>
public string ApiRegisterEndpoint { get; set; } = string.Empty;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Altinn.Notifications.Integrations.Health;
using Altinn.Notifications.Integrations.Kafka.Consumers;
using Altinn.Notifications.Integrations.Kafka.Producers;
using Altinn.Notifications.Integrations.Register;

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -47,9 +48,9 @@ public static void AddAltinnClients(this IServiceCollection services, IConfigura
.Get<PlatformSettings>()
?? throw new ArgumentNullException(nameof(config), "Required PlatformSettings is missing from application configuration");

services
.Configure<PlatformSettings>(config.GetSection(nameof(PlatformSettings)))
.AddHttpClient<IProfileClient, ProfileClient>();
services.Configure<PlatformSettings>(config.GetSection(nameof(PlatformSettings)));
services.AddHttpClient<IProfileClient, ProfileClient>();
services.AddHttpClient<IRegisterClient, RegisterClient>();
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Text.Json.Serialization;

namespace Altinn.Notifications.Integrations.Register
{
/// <summary>
/// A class describing the query model for contact points for organizations
/// </summary>
public class OrgContactPointLookup
{
/// <summary>
/// Gets or sets the list of organization numbers to lookup contact points for
/// </summary>
[JsonPropertyName("organizationNumbers")]
public List<string> OrganizationNumbers { get; set; } = [];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Altinn.Notifications.Core.Models.ContactPoints;

namespace Altinn.Notifications.Integrations.Register
{
/// <summary>
/// A list representation of <see cref="OrganizationContactPoints"/>
/// </summary>
public class OrgContactPointsList
{
/// <summary>
/// A list containing contact points for organizations
/// </summary>
public List<OrganizationContactPoints> ContactPointsList { get; set; } = [];
}
}
Loading

0 comments on commit c7e2b01

Please sign in to comment.