diff --git a/src/Altinn.Notifications.Core/Models/Notification/SmsNotification.cs b/src/Altinn.Notifications.Core/Models/Notification/SmsNotification.cs
new file mode 100644
index 00000000..54077d4d
--- /dev/null
+++ b/src/Altinn.Notifications.Core/Models/Notification/SmsNotification.cs
@@ -0,0 +1,34 @@
+using Altinn.Notifications.Core.Enums;
+
+namespace Altinn.Notifications.Core.Models.Notification;
+
+///
+/// Class describing an sns notification and extends the
+///
+public class SmsNotification : INotification
+{
+ ///
+ public Guid Id { get; internal set; }
+
+ ///
+ public Guid OrderId { get; internal set; }
+
+ ///
+ public DateTime RequestedSendTime { get; internal set; }
+
+ ///
+ public NotificationChannel NotificationChannel { get; } = NotificationChannel.Sms;
+
+ ///
+ /// Get the id of the recipient of the sms notification
+ ///
+ public string? RecipientId { get; internal set; }
+
+ ///
+ /// Get or sets the mobilenumber of the sms notification
+ ///
+ public string RecipientNumber { get; internal set; } = string.Empty;
+
+ ///
+ public NotificationResult SendResult { get; internal set; } = new(SmsNotificationResultType.New, DateTime.UtcNow);
+}
diff --git a/src/Altinn.Notifications.Core/Persistence/ISmsNotificationRepository.cs b/src/Altinn.Notifications.Core/Persistence/ISmsNotificationRepository.cs
index 9172ef4a..0aca03e4 100644
--- a/src/Altinn.Notifications.Core/Persistence/ISmsNotificationRepository.cs
+++ b/src/Altinn.Notifications.Core/Persistence/ISmsNotificationRepository.cs
@@ -1,4 +1,5 @@
using Altinn.Notifications.Core.Models;
+using Altinn.Notifications.Core.Models.Notification;
namespace Altinn.Notifications.Core.Persistence;
@@ -7,6 +8,11 @@ namespace Altinn.Notifications.Core.Persistence;
///
public interface ISmsNotificationRepository
{
+ ///
+ /// Adds a new sms notification to the database
+ ///
+ public Task AddNotification(SmsNotification notification, DateTime expiry);
+
///
/// Retrieves all sms notifications with status 'New'
///
diff --git a/src/Altinn.Notifications.Persistence/Migration/v0.17/01-setup-procedures.sql b/src/Altinn.Notifications.Persistence/Migration/v0.17/01-setup-procedures.sql
new file mode 100644
index 00000000..b2937cce
--- /dev/null
+++ b/src/Altinn.Notifications.Persistence/Migration/v0.17/01-setup-procedures.sql
@@ -0,0 +1,19 @@
+CREATE OR REPLACE PROCEDURE notifications.insertsmsnotification(_orderid uuid,
+ _alternateid uuid,
+ _recipientid TEXT,
+ _mobilenumber TEXT,
+ _result text,
+ _resulttime timestamptz,
+ _expirytime timestamptz
+ )
+LANGUAGE 'plpgsql'
+AS $BODY$
+DECLARE
+__orderid BIGINT := (SELECT _id from notifications.orders
+ where alternateid = _orderid);
+BEGIN
+
+INSERT INTO notifications.smsnotifications(_orderid, alternateid, recipientid, mobilenumber, result, resulttime, expirytime)
+ VALUES (__orderid, _alternateid, _recipientid, _mobilenumber, _result::smsnotificationresulttype, _resulttime, _expirytime);
+END;
+$BODY$
\ No newline at end of file
diff --git a/src/Altinn.Notifications.Persistence/Repository/SmsNotificationRepository.cs b/src/Altinn.Notifications.Persistence/Repository/SmsNotificationRepository.cs
index 332c9139..f3c88e4d 100644
--- a/src/Altinn.Notifications.Persistence/Repository/SmsNotificationRepository.cs
+++ b/src/Altinn.Notifications.Persistence/Repository/SmsNotificationRepository.cs
@@ -1,60 +1,79 @@
using Altinn.Notifications.Core.Enums;
using Altinn.Notifications.Core.Models;
+using Altinn.Notifications.Core.Models.Notification;
using Altinn.Notifications.Core.Persistence;
using Altinn.Notifications.Persistence.Extensions;
using Microsoft.ApplicationInsights;
-
using Npgsql;
+using NpgsqlTypes;
+
+namespace Altinn.Notifications.Persistence.Repository;
-namespace Altinn.Notifications.Persistence.Repository
+///
+/// Implementation of sms repository logic
+///
+public class SmsNotificationRepository : ISmsNotificationRepository
{
+ private readonly NpgsqlDataSource _dataSource;
+ private readonly TelemetryClient? _telemetryClient;
+
+ private const string _insertSmsNotificationSql = "call notifications.insertsmsnotification($1, $2, $3, $4, $5, $6, $7)"; // (__orderid, _alternateid, _recipientid, _mobilenumber, _result, _resulttime, _expirytime)
+ private const string _getSmsNotificationsSql = "select * from notifications.getsms_statusnew_updatestatus()";
+
///
- /// Implementation of sms notification repository logic
+ /// Initializes a new instance of the class.
///
- public class SmsNotificationRepository : ISmsNotificationRepository
+ /// The npgsql data source.
+ /// Telemetry client
+ public SmsNotificationRepository(NpgsqlDataSource dataSource, TelemetryClient? telemetryClient = null)
{
- private readonly NpgsqlDataSource _dataSource;
- private readonly TelemetryClient? _telemetryClient;
+ _dataSource = dataSource;
+ _telemetryClient = telemetryClient;
+ }
- private const string _getSmsNotificationsSql = "select * from notifications.getsms_statusnew_updatestatus()";
+ ///
+ public async Task AddNotification(SmsNotification notification, DateTime expiry)
+ {
+ await using NpgsqlCommand pgcom = _dataSource.CreateCommand(_insertSmsNotificationSql);
+ using TelemetryTracker tracker = new(_telemetryClient, pgcom);
- ///
- /// Initializes a new instance of the class.
- ///
- /// The npgsql data source.
- /// Telemetry client
- public SmsNotificationRepository(NpgsqlDataSource dataSource, TelemetryClient? telemetryClient = null)
- {
- _dataSource = dataSource;
- _telemetryClient = telemetryClient;
- }
+ pgcom.Parameters.AddWithValue(NpgsqlDbType.Uuid, notification.OrderId);
+ pgcom.Parameters.AddWithValue(NpgsqlDbType.Uuid, notification.Id);
+ pgcom.Parameters.AddWithValue(NpgsqlDbType.Text, notification.RecipientId ?? (object)DBNull.Value);
+ pgcom.Parameters.AddWithValue(NpgsqlDbType.Text, notification.RecipientNumber);
+ pgcom.Parameters.AddWithValue(NpgsqlDbType.Text, notification.SendResult.Result.ToString());
+ pgcom.Parameters.AddWithValue(NpgsqlDbType.TimestampTz, notification.SendResult.ResultTime);
+ pgcom.Parameters.AddWithValue(NpgsqlDbType.TimestampTz, expiry);
- ///
- public async Task> GetNewNotifications()
- {
- List searchResult = new();
- await using NpgsqlCommand pgcom = _dataSource.CreateCommand(_getSmsNotificationsSql);
- using TelemetryTracker tracker = new(_telemetryClient, pgcom);
+ await pgcom.ExecuteNonQueryAsync();
+ tracker.Track();
+ }
+
+ ///
+ public async Task> GetNewNotifications()
+ {
+ List searchResult = new();
+ await using NpgsqlCommand pgcom = _dataSource.CreateCommand(_getSmsNotificationsSql);
+ using TelemetryTracker tracker = new(_telemetryClient, pgcom);
- await using (NpgsqlDataReader reader = await pgcom.ExecuteReaderAsync())
+ await using (NpgsqlDataReader reader = await pgcom.ExecuteReaderAsync())
+ {
+ while (await reader.ReadAsync())
{
- while (await reader.ReadAsync())
- {
- EmailContentType emailContentType = (EmailContentType)Enum.Parse(typeof(EmailContentType), reader.GetValue("contenttype"));
-
- var sms = new Sms(
- reader.GetValue("alternateid"),
- reader.GetValue("sendernumber"),
- reader.GetValue("mobilenumber"),
- reader.GetValue("body"));
-
- searchResult.Add(sms);
- }
- }
+ EmailContentType emailContentType = (EmailContentType)Enum.Parse(typeof(EmailContentType), reader.GetValue("contenttype"));
+
+ var sms = new Sms(
+ reader.GetValue("alternateid"),
+ reader.GetValue("sendernumber"),
+ reader.GetValue("mobilenumber"),
+ reader.GetValue("body"));
- tracker.Track();
- return searchResult;
+ searchResult.Add(sms);
+ }
}
+
+ tracker.Track();
+ return searchResult;
}
}
diff --git a/test/Altinn.Notifications.IntegrationTests/Notifications.Persistence/SmsRepositoryTests.cs b/test/Altinn.Notifications.IntegrationTests/Notifications.Persistence/SmsRepositoryTests.cs
new file mode 100644
index 00000000..56c13297
--- /dev/null
+++ b/test/Altinn.Notifications.IntegrationTests/Notifications.Persistence/SmsRepositoryTests.cs
@@ -0,0 +1,64 @@
+using Altinn.Notifications.Core.Enums;
+using Altinn.Notifications.Core.Models.Notification;
+using Altinn.Notifications.Core.Models.Orders;
+using Altinn.Notifications.Core.Persistence;
+using Altinn.Notifications.IntegrationTests.Utils;
+using Altinn.Notifications.Persistence.Repository;
+using Xunit;
+
+namespace Altinn.Notifications.IntegrationTests.Notifications.Persistence;
+
+public class SmsRepositoryTests : IAsyncLifetime
+{
+ private List orderIdsToDelete;
+
+ public SmsRepositoryTests()
+ {
+ orderIdsToDelete = [];
+ }
+
+ public async Task InitializeAsync()
+ {
+ await Task.CompletedTask;
+ }
+
+ public async Task DisposeAsync()
+ {
+ string deleteSql = $@"DELETE from notifications.orders o where o.alternateid in ('{string.Join("','", orderIdsToDelete)}')";
+ await PostgreUtil.RunSql(deleteSql);
+ }
+
+ [Fact]
+ public async Task Create_SmsNotification()
+ {
+ // Arrange
+ Guid orderId = await PostgreUtil.PopulateDBWithOrderAndReturnId();
+ orderIdsToDelete.Add(orderId);
+
+ // Arrange
+ SmsNotificationRepository repo = (SmsNotificationRepository)ServiceUtil
+ .GetServices(new List() { typeof(ISmsNotificationRepository) })
+ .First(i => i.GetType() == typeof(SmsNotificationRepository));
+
+ Guid notificationId = Guid.NewGuid();
+ SmsNotification smsNotification = new()
+ {
+ Id = notificationId,
+ OrderId = orderId,
+ RequestedSendTime = DateTime.UtcNow,
+ RecipientId = "12345678",
+ RecipientNumber = "999999999",
+ };
+
+ await repo.AddNotification(smsNotification, DateTime.UtcNow);
+
+ // Assert
+ string sql = $@"SELECT count(1)
+ FROM notifications.smsnotifications o
+ WHERE o.alternateid = '{notificationId}'";
+
+ int actualCount = await PostgreUtil.RunSqlReturnOutput(sql);
+
+ Assert.Equal(1, actualCount);
+ }
+}