Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ public interface IUserProfileNotificationSettingService
/// </summary>
/// <param name="hdid">The user HDID.</param>
/// <param name="model">
/// The notification setting model containing the notification type and updated delivery channel
/// values.
/// The notification setting model containing the notification type and optional delivery channel values.
/// Only provided channel values are updated and included in the emitted notification preference event.
/// </param>
/// <param name="ct">The cancellation token.</param>
/// <returns>A <see cref="Task{TResult}"/> representing the result of the asynchronous operation.</returns>
/// <returns>A task representing the asynchronous operation.</returns>
Task UpdateAsync(
string hdid,
UserProfileNotificationSettingModel model,
Expand All @@ -53,8 +53,9 @@ Task UpdateAsync(
/// </summary>
/// <param name="hdid">The user HDID.</param>
/// <param name="models">
/// A collection of notification setting models containing the notification types
/// and updated delivery channel values.
/// A collection of notification setting models containing the notification types and optional delivery channel values.
/// Provided channel values are updated. When a channel value is not provided, an existing stored value may still be
/// included in the emitted notification preference event.
/// </param>
/// <param name="commit">Whether to commit changes immediately or defer to the caller's transaction.</param>
/// <param name="ct">The cancellation token.</param>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,45 @@ public async Task UpdateAsync(
UserProfileNotificationSettingModel model,
CancellationToken ct = default)
{
await this.UpdateAsync(hdid, [model], ct: ct);
UserProfile userProfile = await profileDelegate.GetUserProfileAsync(hdid, ct: ct) ?? throw new NotFoundException($"User profile not found for hdid {hdid}");

IReadOnlyList<UserProfileNotificationSetting> existing =
await notificationSettingDelegate.GetAsync(hdid, ct);

UserProfileNotificationSetting setting =
existing.SingleOrDefault(x => x.NotificationType == model.Type) ?? new UserProfileNotificationSetting
{
Hdid = hdid,
NotificationType = model.Type,
};

// Update email preference only when an email value is provided.
if (model.EmailEnabled.HasValue)
{
setting.EmailEnabled = model.EmailEnabled.Value;
}

// Update SMS preference only when an SMS value is provided.
if (model.SmsEnabled.HasValue)
{
setting.SmsEnabled = model.SmsEnabled.Value;
}

IReadOnlyCollection<NotificationTargets> emailNotificationTargets =
model.EmailEnabled.HasValue
? GetTargets(model.Type, model.EmailEnabled.Value, !string.IsNullOrEmpty(userProfile.Email))
: [];

IReadOnlyCollection<NotificationTargets> smsNotificationTargets =
model.SmsEnabled.HasValue
? GetTargets(model.Type, model.SmsEnabled.Value, !string.IsNullOrEmpty(userProfile.SmsNumber))
: [];

MessageEnvelope[] events =
[new(new NotificationChannelPreferencesChangedEvent(hdid, userProfile.SmsNumber, smsNotificationTargets, userProfile.Email, emailNotificationTargets), hdid)];

await notificationSettingDelegate.UpdateAsync(setting, false, ct);
await outboxStore.StoreAsync(events, ct: ct);
}

/// <inheritdoc/>
Expand Down Expand Up @@ -84,6 +122,7 @@ public async Task UpdateAsync(
NotificationType = model.Type,
};

// Use provided email value when present.
if (model.EmailEnabled.HasValue)
{
setting.EmailEnabled = model.EmailEnabled.Value;
Expand All @@ -92,6 +131,14 @@ public async Task UpdateAsync(
GetTargets(model.Type, model.EmailEnabled.Value, !string.IsNullOrEmpty(userProfile.Email)));
}

// Otherwise use existing email value when available.
if (!model.EmailEnabled.HasValue && setting.EmailEnabled.HasValue)
{
emailNotificationTargets.AddRange(
GetTargets(model.Type, setting.EmailEnabled.Value, !string.IsNullOrEmpty(userProfile.Email)));
}

// Use provided SMS value when present.
if (model.SmsEnabled.HasValue)
{
setting.SmsEnabled = model.SmsEnabled.Value;
Expand All @@ -100,6 +147,13 @@ public async Task UpdateAsync(
GetTargets(model.Type, model.SmsEnabled.Value, !string.IsNullOrEmpty(userProfile.SmsNumber)));
}

// Otherwise use existing SMS value when available.
if (!model.SmsEnabled.HasValue && setting.SmsEnabled.HasValue)
{
smsNotificationTargets.AddRange(
GetTargets(model.Type, setting.SmsEnabled.Value, !string.IsNullOrEmpty(userProfile.SmsNumber)));
}

await notificationSettingDelegate.UpdateAsync(setting, false, ct);
}

Expand Down
Loading
Loading