sozsoft-platform/api/src/Sozsoft.Platform.Domain/Data/NotificationTenantDefaultsSeedContributor.cs

159 lines
5.7 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Sozsoft.Notifications.Entities;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
namespace Sozsoft.Platform.Data.Seeds;
/// <summary>
/// Bildirim tipleri ve varsayilan kurallari kiraci kapsamindadir: her kiraci kendi turunu ve
2026-10-05 12:58:59 +00:00
/// kuralini duzenler. Seed dosyalari varsayilan kumeyi tanimlar; host ve kendi veritabani olan
/// kiraci onu dosyadan alir, bu contributor da host veritabanini paylasan yeni kiraciya o kumenin
/// bir kopyasini uretir.
/// <para>
/// Kopya satirlar yeni kimliklerle yazilir; dosyadaki kimlik host kaydinindir ve tum kiracilarda
/// tekrar edilemez. Eslesme ad uzerinden yapilir, bu yuzden ayni kiraci icin ikinci kez
/// calistirildiginda hicbir sey eklenmez.
/// </para>
/// </summary>
public class NotificationTenantDefaultsSeedContributor(
IRepository<NotificationType, Guid> notificationTypeRepository,
IRepository<NotificationRule, Guid> notificationRuleRepository,
IConfiguration configuration,
ILogger<NotificationTenantDefaultsSeedContributor> logger) : IDataSeedContributor, ITransientDependency
{
private const string TypesFile = "App.Notifications.NotificationTypes";
private const string RulesFile = "App.Notifications.NotificationRules";
public async Task SeedAsync(DataSeedContext context)
{
2026-10-05 12:58:59 +00:00
// Seed dosyalarinin uygulandigi veritabani (host ve kendi veritabani olan kiraci) bu satirlari
// ListFormSeedDataApplier ile alir; burada yalnizca host veritabanini paylasan kiracinin kopyasi
// uretilir. Iki yol birden calissaydi ayri veritabanli kiracida tipler iki kez yazilirdi.
if (SeedFileScope.IsEnabled(context))
{
return;
}
var types = ReadRows(TypesFile);
if (types.Count == 0)
{
return;
}
var typeIdByFileId = new Dictionary<string, Guid>(StringComparer.OrdinalIgnoreCase);
var existingTypes = await notificationTypeRepository.GetListAsync();
foreach (var row in types)
{
var name = GetString(row, "Name");
if (name.IsNullOrWhiteSpace())
{
continue;
}
var existing = existingTypes.Find(type => type.Name == name);
if (existing == null)
{
existing = await notificationTypeRepository.InsertAsync(
new NotificationType()
{
TenantId = context.TenantId,
Name = name!,
Description = GetString(row, "Description"),
},
autoSave: true);
}
var fileId = GetString(row, "Id");
if (!fileId.IsNullOrWhiteSpace())
{
typeIdByFileId[fileId!] = existing.Id;
}
}
var existingRules = await notificationRuleRepository.GetListAsync();
foreach (var row in ReadRows(RulesFile))
{
var fileTypeId = GetString(row, "NotificationTypeId");
if (fileTypeId == null || !typeIdByFileId.TryGetValue(fileTypeId, out var typeId))
{
continue;
}
var recipientType = GetString(row, "RecipientType");
var recipientId = GetString(row, "RecipientId");
var channel = GetString(row, "Channel");
var duplicate = existingRules.Exists(rule =>
rule.NotificationTypeId == typeId
&& rule.RecipientType == recipientType
&& rule.RecipientId == recipientId
&& rule.Channel == channel);
if (duplicate)
{
continue;
}
await notificationRuleRepository.InsertAsync(
new NotificationRule()
{
TenantId = context.TenantId,
NotificationTypeId = typeId,
RecipientType = recipientType!,
RecipientId = recipientId,
Channel = channel!,
IsActive = GetBool(row, "IsActive"),
IsFixed = GetBool(row, "IsFixed"),
IsCustomized = GetBool(row, "IsCustomized"),
},
autoSave: true);
}
}
/// <summary>
2026-10-05 12:58:59 +00:00
/// Varsayilan kumeyi veri seed dosyasindan okur; ikinci bir varsayilan
/// listesi kodda tutulmaz. Dosya yoksa kiraci bos baslar, bu bir hata degildir.
/// </summary>
private List<JsonElement> ReadRows(string listFormCode)
{
2026-10-05 12:58:59 +00:00
var path = SeedPathResolver.GetPath(
configuration,
SeedPathResolver.GetDataFilePath(listFormCode).Split('/'));
if (!File.Exists(path))
{
logger.LogInformation("Notification defaults file not found, skipping: {Path}", path);
return [];
}
using var document = JsonDocument.Parse(File.ReadAllText(path));
return document.RootElement.TryGetProperty("Rows", out var rows) && rows.ValueKind == JsonValueKind.Array
? [.. rows.EnumerateArray().Select(row => row.Clone())]
: [];
}
private static string? GetString(JsonElement row, string propertyName)
{
return row.TryGetProperty(propertyName, out var value) && value.ValueKind == JsonValueKind.String
? value.GetString()
: null;
}
private static bool GetBool(JsonElement row, string propertyName)
{
return row.TryGetProperty(propertyName, out var value) && value.ValueKind == JsonValueKind.True;
}
}