diff --git a/src/Altinn.Notifications.Core/Configuration/NotificationOrderConfig.cs b/src/Altinn.Notifications.Core/Configuration/NotificationOrderConfig.cs
index 6ce8b285..93bdeeae 100644
--- a/src/Altinn.Notifications.Core/Configuration/NotificationOrderConfig.cs
+++ b/src/Altinn.Notifications.Core/Configuration/NotificationOrderConfig.cs
@@ -9,4 +9,9 @@ public class NotificationOrderConfig
/// Default from address for email notifications
///
public string DefaultEmailFromAddress { get; set; } = string.Empty;
+
+ ///
+ /// Default sender number for sms notifications
+ ///
+ public string DefaultSmsSenderNumber { get; set; } = string.Empty;
}
diff --git a/src/Altinn.Notifications.Core/Enums/NotificationChannel.cs b/src/Altinn.Notifications.Core/Enums/NotificationChannel.cs
index 7da282be..49e30aa8 100644
--- a/src/Altinn.Notifications.Core/Enums/NotificationChannel.cs
+++ b/src/Altinn.Notifications.Core/Enums/NotificationChannel.cs
@@ -8,5 +8,10 @@ public enum NotificationChannel
///
/// The selected channel for the notification is email.
///
- Email
+ Email,
+
+ ///
+ /// The selected channel for the notification is SMS.
+ ///
+ Sms
}
diff --git a/src/Altinn.Notifications.Core/Enums/NotificationTemplateType.cs b/src/Altinn.Notifications.Core/Enums/NotificationTemplateType.cs
index ae0de091..de2da775 100644
--- a/src/Altinn.Notifications.Core/Enums/NotificationTemplateType.cs
+++ b/src/Altinn.Notifications.Core/Enums/NotificationTemplateType.cs
@@ -6,6 +6,7 @@
///
public enum NotificationTemplateType
{
- Email
+ Email,
+ Sms
}
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
diff --git a/src/Altinn.Notifications.Core/Extensions/ServiceCollectionExtensions.cs b/src/Altinn.Notifications.Core/Extensions/ServiceCollectionExtensions.cs
index 660c7c5e..208a8f3f 100644
--- a/src/Altinn.Notifications.Core/Extensions/ServiceCollectionExtensions.cs
+++ b/src/Altinn.Notifications.Core/Extensions/ServiceCollectionExtensions.cs
@@ -32,7 +32,7 @@ public static void AddCoreServices(this IServiceCollection services, IConfigurat
.AddSingleton()
.AddSingleton()
.AddSingleton()
- .AddSingleton()
+ .AddSingleton()
.AddSingleton()
.AddSingleton()
.AddSingleton()
diff --git a/src/Altinn.Notifications.Core/Models/NotificationTemplate/INotificationTemplate.cs b/src/Altinn.Notifications.Core/Models/NotificationTemplate/INotificationTemplate.cs
index c8f3ce71..5329fc08 100644
--- a/src/Altinn.Notifications.Core/Models/NotificationTemplate/INotificationTemplate.cs
+++ b/src/Altinn.Notifications.Core/Models/NotificationTemplate/INotificationTemplate.cs
@@ -8,6 +8,7 @@ namespace Altinn.Notifications.Core.Models.NotificationTemplate;
/// Base class for a notification template
///
[JsonDerivedType(typeof(EmailTemplate), "email")]
+[JsonDerivedType(typeof(SmsTemplate), "sms")]
[JsonPolymorphic(TypeDiscriminatorPropertyName = "$")]
public interface INotificationTemplate
{
diff --git a/src/Altinn.Notifications.Core/Models/NotificationTemplate/SmsTemplate.cs b/src/Altinn.Notifications.Core/Models/NotificationTemplate/SmsTemplate.cs
new file mode 100644
index 00000000..9d1cb2db
--- /dev/null
+++ b/src/Altinn.Notifications.Core/Models/NotificationTemplate/SmsTemplate.cs
@@ -0,0 +1,39 @@
+using Altinn.Notifications.Core.Enums;
+
+namespace Altinn.Notifications.Core.Models.NotificationTemplate;
+
+///
+/// Template for an SMS notification
+///
+public class SmsTemplate : INotificationTemplate
+{
+ ///
+ public NotificationTemplateType Type { get; internal set; }
+
+ ///
+ /// Gets the number from which the SMS is created by the template
+ ///
+ public string SenderNumber { get; internal set; } = string.Empty;
+
+ ///
+ /// Gets the body of SMSs created by the template
+ ///
+ public string Body { get; internal set; } = string.Empty;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public SmsTemplate(string? senderNumber, string body)
+ {
+ SenderNumber = senderNumber ?? string.Empty;
+ Body = body;
+ Type = NotificationTemplateType.Sms;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ internal SmsTemplate()
+ {
+ }
+}
diff --git a/src/Altinn.Notifications.Core/Services/Interfaces/IEmailNotificationOrderService.cs b/src/Altinn.Notifications.Core/Services/Interfaces/IOrderRequestService.cs
similarity index 59%
rename from src/Altinn.Notifications.Core/Services/Interfaces/IEmailNotificationOrderService.cs
rename to src/Altinn.Notifications.Core/Services/Interfaces/IOrderRequestService.cs
index c817ba1f..b9edf362 100644
--- a/src/Altinn.Notifications.Core/Services/Interfaces/IEmailNotificationOrderService.cs
+++ b/src/Altinn.Notifications.Core/Services/Interfaces/IOrderRequestService.cs
@@ -4,14 +4,14 @@
namespace Altinn.Notifications.Core.Services.Interfaces;
///
-/// Interface for the email notification order service
+/// Interface for the notification order service
///
-public interface IEmailNotificationOrderService
+public interface IOrderRequestService
{
///
/// Registers a new order
///
- /// The email notification order request
+ /// The notification order request
/// The registered notification order
- public Task<(NotificationOrder? Order, ServiceError? Error)> RegisterEmailNotificationOrder(NotificationOrderRequest orderRequest);
+ public Task<(NotificationOrder? Order, ServiceError? Error)> RegisterNotificationOrder(NotificationOrderRequest orderRequest);
}
diff --git a/src/Altinn.Notifications.Core/Services/EmailNotificationOrderService.cs b/src/Altinn.Notifications.Core/Services/OrderRequestService.cs
similarity index 57%
rename from src/Altinn.Notifications.Core/Services/EmailNotificationOrderService.cs
rename to src/Altinn.Notifications.Core/Services/OrderRequestService.cs
index 93515f37..a772e65e 100644
--- a/src/Altinn.Notifications.Core/Services/EmailNotificationOrderService.cs
+++ b/src/Altinn.Notifications.Core/Services/OrderRequestService.cs
@@ -10,33 +10,35 @@
namespace Altinn.Notifications.Core.Services;
///
-/// Implementation of the .
+/// Implementation of the .
///
-public class EmailNotificationOrderService : IEmailNotificationOrderService
+public class OrderRequestService : IOrderRequestService
{
private readonly IOrderRepository _repository;
private readonly IGuidService _guid;
private readonly IDateTimeService _dateTime;
- private readonly string _defaultFromAddress;
+ private readonly string _defaultEmailFromAddress;
+ private readonly string _defaultSmsSender;
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
- public EmailNotificationOrderService(IOrderRepository repository, IGuidService guid, IDateTimeService dateTime, IOptions config)
+ public OrderRequestService(IOrderRepository repository, IGuidService guid, IDateTimeService dateTime, IOptions config)
{
_repository = repository;
_guid = guid;
_dateTime = dateTime;
- _defaultFromAddress = config.Value.DefaultEmailFromAddress;
+ _defaultEmailFromAddress = config.Value.DefaultEmailFromAddress;
+ _defaultSmsSender = config.Value.DefaultSmsSenderNumber;
}
///
- public async Task<(NotificationOrder? Order, ServiceError? Error)> RegisterEmailNotificationOrder(NotificationOrderRequest orderRequest)
+ public async Task<(NotificationOrder? Order, ServiceError? Error)> RegisterNotificationOrder(NotificationOrderRequest orderRequest)
{
Guid orderId = _guid.NewGuid();
DateTime created = _dateTime.UtcNow();
- var templates = SetFromAddressIfNotDefined(orderRequest.Templates);
+ var templates = SetSenderIfNotDefined(orderRequest.Templates);
var order = new NotificationOrder(
orderId,
@@ -53,11 +55,16 @@ public EmailNotificationOrderService(IOrderRepository repository, IGuidService g
return (savedOrder, null);
}
- private List SetFromAddressIfNotDefined(List templates)
+ private List SetSenderIfNotDefined(List templates)
{
foreach (var template in templates.OfType().Where(template => string.IsNullOrEmpty(template.FromAddress)))
{
- template.FromAddress = _defaultFromAddress;
+ template.FromAddress = _defaultEmailFromAddress;
+ }
+
+ foreach (var template in templates.OfType().Where(template => string.IsNullOrEmpty(template.SenderNumber)))
+ {
+ template.SenderNumber = _defaultSmsSender;
}
return templates;
diff --git a/src/Altinn.Notifications/Controllers/EmailNotificationOrdersController.cs b/src/Altinn.Notifications/Controllers/EmailNotificationOrdersController.cs
index 7e20473e..ebc63eb6 100644
--- a/src/Altinn.Notifications/Controllers/EmailNotificationOrdersController.cs
+++ b/src/Altinn.Notifications/Controllers/EmailNotificationOrdersController.cs
@@ -29,15 +29,15 @@ namespace Altinn.Notifications.Controllers;
public class EmailNotificationOrdersController : ControllerBase
{
private readonly IValidator _validator;
- private readonly IEmailNotificationOrderService _orderService;
+ private readonly IOrderRequestService _orderRequestService;
///
/// Initializes a new instance of the class.
///
- public EmailNotificationOrdersController(IValidator validator, IEmailNotificationOrderService orderService)
+ public EmailNotificationOrdersController(IValidator validator, IOrderRequestService orderRequestService)
{
_validator = validator;
- _orderService = orderService;
+ _orderRequestService = orderRequestService;
}
///
@@ -71,7 +71,7 @@ public async Task> Post(EmailNotificationOrderRequestEx
}
var orderRequest = emailNotificationOrderRequest.MapToOrderRequest(creator);
- (NotificationOrder? registeredOrder, ServiceError? error) = await _orderService.RegisterEmailNotificationOrder(orderRequest);
+ (NotificationOrder? registeredOrder, ServiceError? error) = await _orderRequestService.RegisterNotificationOrder(orderRequest);
if (error != null)
{
diff --git a/test/Altinn.Notifications.IntegrationTests/Notifications/EmailNotificationsOrderController/EmailNotificationOrdersControllerTests.cs b/test/Altinn.Notifications.IntegrationTests/Notifications/EmailNotificationsOrderController/EmailNotificationOrdersControllerTests.cs
index c7ec540e..cfe44357 100644
--- a/test/Altinn.Notifications.IntegrationTests/Notifications/EmailNotificationsOrderController/EmailNotificationOrdersControllerTests.cs
+++ b/test/Altinn.Notifications.IntegrationTests/Notifications/EmailNotificationsOrderController/EmailNotificationOrdersControllerTests.cs
@@ -172,8 +172,8 @@ public async Task Post_UserClaimsPrincipal_Forbidden()
public async Task Post_ServiceReturnsError_ServerError()
{
// Arrange
- Mock serviceMock = new();
- serviceMock.Setup(s => s.RegisterEmailNotificationOrder(It.IsAny()))
+ Mock serviceMock = new();
+ serviceMock.Setup(s => s.RegisterNotificationOrder(It.IsAny()))
.ReturnsAsync((null, new ServiceError(500)));
HttpClient client = GetTestClient(orderService: serviceMock.Object);
@@ -196,8 +196,8 @@ public async Task Post_ServiceReturnsError_ServerError()
public async Task Post_ValidScope_ServiceReturnsOrder_Accepted()
{
// Arrange
- Mock serviceMock = new();
- serviceMock.Setup(s => s.RegisterEmailNotificationOrder(It.IsAny()))
+ Mock serviceMock = new();
+ serviceMock.Setup(s => s.RegisterNotificationOrder(It.IsAny()))
.Callback(orderRequest =>
{
var emailTemplate = orderRequest.Templates
@@ -235,8 +235,8 @@ public async Task Post_ValidScope_ServiceReturnsOrder_Accepted()
public async Task Post_ValidAccessToken_ServiceReturnsOrder_Accepted()
{
// Arrange
- Mock serviceMock = new();
- serviceMock.Setup(s => s.RegisterEmailNotificationOrder(It.IsAny()))
+ Mock serviceMock = new();
+ serviceMock.Setup(s => s.RegisterNotificationOrder(It.IsAny()))
.Callback(orderRequest =>
{
var emailTemplate = orderRequest.Templates
@@ -274,9 +274,9 @@ public async Task Post_ValidAccessToken_ServiceReturnsOrder_Accepted()
public async Task Post_OrderWithoutFromAddress_StringEmptyUsedAsServiceInput_Accepted()
{
// Arrange
- Mock serviceMock = new();
+ Mock serviceMock = new();
- serviceMock.Setup(s => s.RegisterEmailNotificationOrder(It.IsAny()))
+ serviceMock.Setup(s => s.RegisterNotificationOrder(It.IsAny()))
.Callback(orderRequest =>
{
var emailTemplate = orderRequest.Templates
@@ -321,7 +321,7 @@ public async Task Post_OrderWithoutFromAddress_StringEmptyUsedAsServiceInput_Acc
serviceMock.VerifyAll();
}
- private HttpClient GetTestClient(IValidator? validator = null, IEmailNotificationOrderService? orderService = null)
+ private HttpClient GetTestClient(IValidator? validator = null, IOrderRequestService? orderService = null)
{
if (validator == null)
{
@@ -333,7 +333,7 @@ private HttpClient GetTestClient(IValidator? v
if (orderService == null)
{
- var orderServiceMock = new Mock();
+ var orderServiceMock = new Mock();
orderService = orderServiceMock.Object;
}
diff --git a/test/Altinn.Notifications.Tests/Notifications.Core/TestingServices/EmailNotificationOrderServiceTests.cs b/test/Altinn.Notifications.Tests/Notifications.Core/TestingServices/OrderRequestServiceTests.cs
similarity index 51%
rename from test/Altinn.Notifications.Tests/Notifications.Core/TestingServices/EmailNotificationOrderServiceTests.cs
rename to test/Altinn.Notifications.Tests/Notifications.Core/TestingServices/OrderRequestServiceTests.cs
index 67d26f15..281e399d 100644
--- a/test/Altinn.Notifications.Tests/Notifications.Core/TestingServices/EmailNotificationOrderServiceTests.cs
+++ b/test/Altinn.Notifications.Tests/Notifications.Core/TestingServices/OrderRequestServiceTests.cs
@@ -18,10 +18,10 @@
namespace Altinn.Notifications.Tests.Notifications.Core.TestingServices;
-public class EmailNotificationOrderServiceTests
+public class OrderRequestServiceTests
{
[Fact]
- public async Task RegisterEmailNotificationOrder_ExpectedInputToRepository()
+ public async Task RegisterNotificationOrder_ForEmail_ExpectedInputToRepository()
{
// Arrange
DateTime sendTime = DateTime.UtcNow;
@@ -59,7 +59,7 @@ public async Task RegisterEmailNotificationOrder_ExpectedInputToRepository()
var service = GetTestService(repoMock.Object, id, createdTime);
// Act
- (NotificationOrder? actual, ServiceError? _) = await service.RegisterEmailNotificationOrder(input);
+ (NotificationOrder? actual, ServiceError? _) = await service.RegisterNotificationOrder(input);
// Assert
Assert.Equivalent(expected, actual, true);
@@ -67,7 +67,7 @@ public async Task RegisterEmailNotificationOrder_ExpectedInputToRepository()
}
[Fact]
- public async Task RegisterEmailNotificationOrder_NoFromAddressDefaultInserted()
+ public async Task RegisterNotificationOrder_ForEmail_NoFromAddressDefaultInserted()
{
// Arrange
DateTime sendTime = DateTime.UtcNow;
@@ -105,14 +105,106 @@ public async Task RegisterEmailNotificationOrder_NoFromAddressDefaultInserted()
var service = GetTestService(repoMock.Object, id, createdTime);
// Act
- (NotificationOrder? actual, ServiceError? _) = await service.RegisterEmailNotificationOrder(input);
+ (NotificationOrder? actual, ServiceError? _) = await service.RegisterNotificationOrder(input);
// Assert
Assert.Equivalent(expected, actual, true);
repoMock.VerifyAll();
}
- public static EmailNotificationOrderService GetTestService(IOrderRepository? repository = null, Guid? guid = null, DateTime? dateTime = null)
+ [Fact]
+ public async Task RegisterNotificationOrder_ForSms_ExpectedInputToRepository()
+ {
+ // Arrange
+ DateTime sendTime = DateTime.UtcNow;
+ DateTime createdTime = DateTime.UtcNow.AddMinutes(-2);
+ Guid id = Guid.NewGuid();
+
+ NotificationOrder expected = new()
+ {
+ Id = id,
+ Created = createdTime,
+ Creator = new("ttd"),
+ NotificationChannel = NotificationChannel.Sms,
+ RequestedSendTime = sendTime,
+ Recipients = { },
+ SendersReference = "senders-reference",
+ Templates = { new SmsTemplate { Body = "sms-body", SenderNumber = "Skatteetaten" } }
+ };
+
+ NotificationOrderRequest input = new()
+ {
+ Creator = new Creator("ttd"),
+
+ NotificationChannel = NotificationChannel.Sms,
+ Recipients = { },
+ SendersReference = "senders-reference",
+ RequestedSendTime = sendTime,
+ Templates = { new SmsTemplate { Body = "sms-body", SenderNumber = "Skatteetaten" } }
+ };
+
+ Mock repoMock = new();
+ repoMock
+ .Setup(r => r.Create(It.IsAny()))
+ .ReturnsAsync((NotificationOrder order) => order);
+
+ var service = GetTestService(repoMock.Object, id, createdTime);
+
+ // Act
+ (NotificationOrder? actual, ServiceError? _) = await service.RegisterNotificationOrder(input);
+
+ // Assert
+ Assert.Equivalent(expected, actual, true);
+ repoMock.VerifyAll();
+ }
+
+ [Fact]
+ public async Task RegisterNotificationOrder_ForSms_NoSenderNumberDefaultInserted()
+ {
+ // Arrange
+ DateTime sendTime = DateTime.UtcNow;
+ DateTime createdTime = DateTime.UtcNow.AddMinutes(-2);
+ Guid id = Guid.NewGuid();
+
+ NotificationOrder expected = new()
+ {
+ Id = id,
+ Created = createdTime,
+ Creator = new("ttd"),
+ NotificationChannel = NotificationChannel.Sms,
+ RequestedSendTime = sendTime,
+ Recipients = { },
+ SendersReference = "senders-reference",
+ Templates = { new SmsTemplate { Body = "sms-body", SenderNumber = "TestDefaultSmsSenderNumberNumber" } }
+ };
+
+ NotificationOrderRequest input = new()
+ {
+ Creator = new Creator("ttd"),
+
+ NotificationChannel = NotificationChannel.Sms,
+ Recipients = { },
+ SendersReference = "senders-reference",
+ RequestedSendTime = sendTime,
+ Templates = { new SmsTemplate { Body = "sms-body" } }
+ };
+
+ Mock repoMock = new();
+ repoMock
+ .Setup(r => r.Create(It.IsAny()))
+ .ReturnsAsync((NotificationOrder order) => order);
+
+ var service = GetTestService(repoMock.Object, id, createdTime);
+
+ // Act
+ (NotificationOrder? actual, ServiceError? _) = await service.RegisterNotificationOrder(input);
+
+ // Assert
+ Assert.Equivalent(expected, actual, true);
+ repoMock.VerifyAll();
+ }
+
+ public static OrderRequestService GetTestService(IOrderRepository? repository = null, Guid? guid = null, DateTime? dateTime = null)
{
if (repository == null)
{
@@ -130,8 +222,9 @@ public static EmailNotificationOrderService GetTestService(IOrderRepository? rep
var config = Options.Create(new()
{
- DefaultEmailFromAddress = "noreply@altinn.no"
+ DefaultEmailFromAddress = "noreply@altinn.no",
+ DefaultSmsSenderNumber = "TestDefaultSmsSenderNumberNumber"
});
- return new EmailNotificationOrderService(repository, guidMock.Object, dateTimeMock.Object, config);
+ return new OrderRequestService(repository, guidMock.Object, dateTimeMock.Object, config);
}
}