Initial commit
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using PowderCoating.Application.Interfaces;
|
||||
using PowderCoating.Core.Entities;
|
||||
using PowderCoating.Infrastructure.Data;
|
||||
|
||||
namespace PowderCoating.Infrastructure.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Database-backed key/value store for platform-wide configuration settings managed by
|
||||
/// SuperAdmins at <c>/PlatformSettings</c>. Settings are persisted in the <c>PlatformSettings</c>
|
||||
/// table as free-form strings; callers are responsible for parsing typed values (booleans, ints,
|
||||
/// etc.) from the returned strings. Rows are seeded at startup so that every expected key always
|
||||
/// has a row — the <see cref="SetAsync"/> guard that inserts a missing row is a safety net for
|
||||
/// future migrations, not the normal path.
|
||||
/// </summary>
|
||||
public class PlatformSettingsService : IPlatformSettingsService
|
||||
{
|
||||
private readonly ApplicationDbContext _db;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs the service with a direct <see cref="ApplicationDbContext"/> reference.
|
||||
/// Direct context access is used (rather than a repository) because
|
||||
/// <c>PlatformSetting</c> does not inherit <c>BaseEntity</c> and therefore is not managed
|
||||
/// by the generic <c>Repository<T></c> or filtered by the global query filters.
|
||||
/// </summary>
|
||||
public PlatformSettingsService(ApplicationDbContext db)
|
||||
{
|
||||
_db = db;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the value for the given <paramref name="key"/>, or <c>null</c> when the key
|
||||
/// does not exist. Uses <c>AsNoTracking</c> because reads are more frequent than writes and
|
||||
/// the caller never modifies the returned value directly.
|
||||
/// </summary>
|
||||
public async Task<string?> GetAsync(string key)
|
||||
{
|
||||
var setting = await _db.PlatformSettings
|
||||
.AsNoTracking()
|
||||
.FirstOrDefaultAsync(s => s.Key == key);
|
||||
return setting?.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates or updates the platform setting identified by <paramref name="key"/>.
|
||||
/// Records <paramref name="updatedBy"/> (typically the SuperAdmin's username) and
|
||||
/// <c>UpdatedAt</c> (UTC) for audit purposes. Inserts a new row if the key is missing —
|
||||
/// this should only happen when a new setting key is introduced without a corresponding
|
||||
/// seed migration. Calls <c>SaveChangesAsync</c> directly rather than going through
|
||||
/// <c>IUnitOfWork</c> to avoid inadvertently flushing unrelated tracked changes from the
|
||||
/// caller's scope.
|
||||
/// </summary>
|
||||
public async Task SetAsync(string key, string? value, string? updatedBy = null)
|
||||
{
|
||||
var setting = await _db.PlatformSettings.FirstOrDefaultAsync(s => s.Key == key);
|
||||
if (setting == null)
|
||||
{
|
||||
// Shouldn't happen in normal use (rows are seeded), but handle gracefully
|
||||
setting = new PlatformSetting { Key = key };
|
||||
_db.PlatformSettings.Add(setting);
|
||||
}
|
||||
|
||||
setting.Value = value;
|
||||
setting.UpdatedAt = DateTime.UtcNow;
|
||||
setting.UpdatedBy = updatedBy;
|
||||
|
||||
await _db.SaveChangesAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all platform settings ordered by group then key, suitable for rendering the
|
||||
/// SuperAdmin settings management UI. Results are read with <c>AsNoTracking</c> for
|
||||
/// performance; the UI renders them read-only and individual edits go through
|
||||
/// <see cref="SetAsync"/>.
|
||||
/// </summary>
|
||||
public async Task<IReadOnlyList<PlatformSetting>> GetAllAsync()
|
||||
{
|
||||
return await _db.PlatformSettings
|
||||
.AsNoTracking()
|
||||
.OrderBy(s => s.GroupName)
|
||||
.ThenBy(s => s.Key)
|
||||
.ToListAsync();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user