Skip to content

Commit

Permalink
Core + persistence logic for sms notification summaries #GPCActive (#416
Browse files Browse the repository at this point in the history
)

* Core logic for supporting sms notification summaries
* Repository logic for supporting sms notification summaries
  • Loading branch information
acn-sbuad authored Feb 8, 2024
1 parent a5a4672 commit 51b2fd7
Show file tree
Hide file tree
Showing 21 changed files with 559 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ public static void AddCoreServices(this IServiceCollection services, IConfigurat
.AddSingleton<ISmsOrderProcessingService, SmsOrderProcessingService>()
.AddSingleton<IGetOrderService, GetOrderService>()
.AddSingleton<IOrderRequestService, OrderRequestService>()
.AddSingleton<INotificationSummaryService, NotificationSummaryService>()
.AddSingleton<IEmailNotificationSummaryService, EmailNotificationSummaryService>()
.AddSingleton<IEmailNotificationService, EmailNotificationService>()
.AddSingleton<ISmsNotificationService, SmsNotificationService>()
.AddSingleton<ISmsNotificationSummaryService, SmsNotificationSummaryService>()
.AddSingleton<IAltinnServiceUpdateService, AltinnServiceUpdateService>()
.AddSingleton<INotificationsEmailServiceUpdateService, NotificationsEmailServiceUpdateService>()
.Configure<KafkaSettings>(config.GetSection("KafkaSettings"))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
namespace Altinn.Notifications.Core.Models.Notification
{
/// <summary>
/// An implementation of <see cref="INotificationSummary{TClass}"/> for sms notifications"/>
/// </summary>
public class SmsNotificationSummary : INotificationSummary<SmsNotificationWithResult>
{
/// <inheritdoc/>
public Guid OrderId { get; set; }

/// <inheritdoc/>
public string? SendersReference { get; set; }

/// <inheritdoc/>
public int Generated { get; internal set; }

/// <inheritdoc/>
public int Succeeded { get; internal set; }

/// <inheritdoc/>
public List<SmsNotificationWithResult> Notifications { get; set; } = new List<SmsNotificationWithResult>();

/// <summary>
/// Initializes a new instance of the <see cref="SmsNotificationSummary"/> class.
/// </summary>
public SmsNotificationSummary(Guid orderId)
{
OrderId = orderId;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using Altinn.Notifications.Core.Enums;
using Altinn.Notifications.Core.Models.Recipients;

namespace Altinn.Notifications.Core.Models.Notification
{
/// <summary>
/// An implementation of <see cref="INotificationWithResult{TClass, T}"/> for sms notifications"/>
/// Using the <see cref="SmsRecipient"/> as recipient type and the <see cref="SmsNotificationResultType"/> as result type
/// </summary>
public class SmsNotificationWithResult : INotificationWithResult<SmsRecipient, SmsNotificationResultType>
{
/// <inheritdoc/>
public Guid Id { get; }

/// <inheritdoc/>
public bool Succeeded { get; internal set; }

/// <inheritdoc/>
public SmsRecipient Recipient { get; }

/// <inheritdoc/>
public NotificationResult<SmsNotificationResultType> ResultStatus { get; }

/// <summary>
/// Initializes a new instance of the <see cref="SmsNotificationWithResult"/> class.
/// </summary>
public SmsNotificationWithResult(Guid id, SmsRecipient recipient, NotificationResult<SmsNotificationResultType> result)
{
Id = id;
Recipient = recipient;
ResultStatus = result;
}

/// <summary>
/// Initializes a new instance of the <see cref="SmsNotificationWithResult"/> class.
/// </summary>
internal SmsNotificationWithResult(Guid id, bool succeeded, SmsRecipient recipient, NotificationResult<SmsNotificationResultType> result)
{
Id = id;
Succeeded = succeeded;
Recipient = recipient;
ResultStatus = result;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,10 @@ public interface INotificationSummaryRepository
/// </summary>
/// <returns>A partial email notification summary object</returns>
public Task<EmailNotificationSummary?> GetEmailSummary(Guid orderId, string creator);

/// <summary>
/// Retrieves all sms notifications for the provided order id in an sms notification summary
/// </summary>
/// <returns>A partial sms notification summary object</returns>
public Task<SmsNotificationSummary?> GetSmsSummary(Guid orderId, string creator);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
namespace Altinn.Notifications.Core.Services
{
/// <summary>
/// Implementation of <see cref="INotificationSummaryService"/>
/// Implementation of <see cref="IEmailNotificationSummaryService"/>
/// </summary>
public class NotificationSummaryService : INotificationSummaryService
public class EmailNotificationSummaryService : IEmailNotificationSummaryService
{
private readonly INotificationSummaryRepository _summaryRepository;
private readonly static Dictionary<EmailNotificationResultType, string> _emailResultDescriptions = new()
Expand All @@ -22,7 +22,7 @@ public class NotificationSummaryService : INotificationSummaryService
{ EmailNotificationResultType.Failed_RecipientNotIdentified, "The email was not sent because the recipient's email address was not found." },
{ EmailNotificationResultType.Failed_InvalidEmailFormat, "The email was not sent because the recipient’s email address is in an invalid format." },
{ EmailNotificationResultType.Failed_SupressedRecipient, "The email was not sent because the recipient’s email address is suppressed by the third party email service." },
{ EmailNotificationResultType.Failed_TransientError, "The email was not sent due to a transient error. We will retry sending the email." }
{ EmailNotificationResultType.Failed_TransientError, "The email was not sent due to a transient error. We will retry sending the email." }
};

private readonly static List<EmailNotificationResultType> _successResults = new()
Expand All @@ -32,15 +32,15 @@ public class NotificationSummaryService : INotificationSummaryService
};

/// <summary>
/// Initializes a new instance of the <see cref="NotificationSummaryService"/> class.
/// Initializes a new instance of the <see cref="EmailNotificationSummaryService"/> class.
/// </summary>
public NotificationSummaryService(INotificationSummaryRepository summaryRepository)
public EmailNotificationSummaryService(INotificationSummaryRepository summaryRepository)
{
_summaryRepository = summaryRepository;
}

/// <inheritdoc/>
public async Task<Result<EmailNotificationSummary, ServiceError>> GetEmailSummary(Guid orderId, string creator)
public async Task<Result<EmailNotificationSummary, ServiceError>> GetSummary(Guid orderId, string creator)
{
EmailNotificationSummary? summary = await _summaryRepository.GetEmailSummary(orderId, creator);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
namespace Altinn.Notifications.Core.Services.Interfaces
{
/// <summary>
/// Interface describing the notification summary service
/// Interface describing the email notification summary service
/// </summary>
public interface INotificationSummaryService
public interface IEmailNotificationSummaryService
{
/// <summary>
/// Gets a summary of all the generated email notifications for the provided order id
/// </summary>
/// <param name="orderId">The order id to find notifications for</param>
/// <param name="creator">The creator of the order</param>
public Task<Result<EmailNotificationSummary, ServiceError>> GetEmailSummary(Guid orderId, string creator);
public Task<Result<EmailNotificationSummary, ServiceError>> GetSummary(Guid orderId, string creator);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Altinn.Notifications.Core.Models.Notification;
using Altinn.Notifications.Core.Shared;

namespace Altinn.Notifications.Core.Services.Interfaces
{
/// <summary>
/// Interface describing the sms notification summary service
/// </summary>
public interface ISmsNotificationSummaryService
{
/// <summary>
/// Gets a summary of all the generated sms notifications for the provided order id
/// </summary>
/// <param name="orderId">The order id to find notifications for</param>
/// <param name="creator">The creator of the order</param>
public Task<Result<SmsNotificationSummary, ServiceError>> GetSummary(Guid orderId, string creator);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using Altinn.Notifications.Core.Enums;
using Altinn.Notifications.Core.Models.Notification;
using Altinn.Notifications.Core.Persistence;
using Altinn.Notifications.Core.Services.Interfaces;
using Altinn.Notifications.Core.Shared;

namespace Altinn.Notifications.Core.Services
{
/// <summary>
/// Implementation of <see cref="ISmsNotificationSummaryService"/>
/// </summary>
public class SmsNotificationSummaryService : ISmsNotificationSummaryService
{
private readonly INotificationSummaryRepository _summaryRepository;
private readonly static Dictionary<SmsNotificationResultType, string> _smsResultDescriptions = new()
{
{ SmsNotificationResultType.New, "The SMS has been created, but has not been picked up for processing yet." },
{ SmsNotificationResultType.Sending, "The SMS is being processed and will be attempted sent shortly." },
{ SmsNotificationResultType.Accepted, "The SMS has been accepted by the gateway service and will be sent shortly." },
{ SmsNotificationResultType.Failed, "The SMS was not sent due to an unspecified failure." },
{ SmsNotificationResultType.Failed_RecipientNotIdentified, "The SMS was not sent because the recipient's SMS address was not found." },
{ SmsNotificationResultType.Failed_InvalidRecipient, "The SMS was not sent because the recipient number was invalid." }
};

private readonly static List<SmsNotificationResultType> _successResults = new()
{
SmsNotificationResultType.Accepted
};

/// <summary>
/// Initializes a new instance of the <see cref="SmsNotificationSummaryService"/> class.
/// </summary>
public SmsNotificationSummaryService(INotificationSummaryRepository summaryRepository)
{
_summaryRepository = summaryRepository;
}

/// <inheritdoc/>
public async Task<Result<SmsNotificationSummary, ServiceError>> GetSummary(Guid orderId, string creator)
{
SmsNotificationSummary? summary = await _summaryRepository.GetSmsSummary(orderId, creator);

if (summary == null)
{
return new ServiceError(404);
}

if (summary.Notifications.Count != 0)
{
ProcessNotificationResults(summary);
}

return summary;
}

/// <summary>
/// Processes the notification results setting counts and descriptions
/// </summary>
internal static void ProcessNotificationResults(SmsNotificationSummary summary)
{
summary.Generated = summary.Notifications.Count;

foreach (SmsNotificationWithResult notification in summary.Notifications)
{
NotificationResult<SmsNotificationResultType> resultStatus = notification.ResultStatus;
if (IsSuccessResult(resultStatus.Result))
{
notification.Succeeded = true;
++summary.Succeeded;
}

resultStatus.SetResultDescription(GetResultDescription(resultStatus.Result));
}
}

/// <summary>
/// Checks if the <see cref="SmsNotificationResultType"/> is a success result
/// </summary>
internal static bool IsSuccessResult(SmsNotificationResultType result)
{
return _successResults.Contains(result);
}

/// <summary>
/// Gets the English description of the <see cref="SmsNotificationResultType"/>"
/// </summary>
internal static string GetResultDescription(SmsNotificationResultType result)
{
return _smsResultDescriptions[result];
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
CREATE OR REPLACE FUNCTION notifications.getsmssummary(
_alternateorderid uuid,
_creatorname text)
RETURNS TABLE(
sendersreference text,
alternateid uuid,
recipientid text,
mobilenumber text,
result smsnotificationresulttype,
resulttime timestamptz)
LANGUAGE 'plpgsql'
AS $BODY$

BEGIN
RETURN QUERY
SELECT o.sendersreference, n.alternateid, n.recipientid, n.mobilenumber, n.result, n.resulttime
FROM notifications.smsnotifications n
LEFT JOIN notifications.orders o ON n._orderid = o._id
WHERE o.alternateid = _alternateorderid
and o.creatorname = _creatorname;
IF NOT FOUND THEN
RETURN QUERY
SELECT o.sendersreference, NULL::uuid, NULL::text, NULL::text, NULL::smsnotificationresulttype, NULL::timestamptz
FROM notifications.orders o
WHERE o.alternateid = _alternateorderid
and o.creatorname = _creatorname;
END IF;
END;
$BODY$;
Loading

0 comments on commit 51b2fd7

Please sign in to comment.