108 lines
4.5 KiB
C#
108 lines
4.5 KiB
C#
using Distribution.Infra.UoW;
|
|
using Distribution.Models;
|
|
|
|
namespace Distribution.Features.SysConfig;
|
|
|
|
public class SysConfigService(ISysConfigRepository repo, IUnitOfWork uow)
|
|
{
|
|
public const string KeyInvoiceCreationMode = "InvoiceCreationMode";
|
|
|
|
public const string KeySerialNumberTrackingEnabled = "Feature.SerialNumberTracking";
|
|
public const string KeyBatchTrackingEnabled = "Feature.BatchTracking";
|
|
public const string KeyExpiryDateTrackingEnabled = "Feature.ExpiryDateTracking";
|
|
public const string KeyWarrantyTrackingEnabled = "Feature.WarrantyTracking";
|
|
public const string KeyCustomWarrantyOverrideEnabled = "Feature.CustomWarrantyOverride";
|
|
public const string KeyDefaultWarrantyPeriodDays = "Feature.DefaultWarrantyPeriodDays";
|
|
|
|
private static readonly string[] BooleanFeatureKeys =
|
|
[
|
|
KeySerialNumberTrackingEnabled,
|
|
KeyBatchTrackingEnabled,
|
|
KeyExpiryDateTrackingEnabled,
|
|
KeyWarrantyTrackingEnabled,
|
|
KeyCustomWarrantyOverrideEnabled,
|
|
];
|
|
|
|
public async Task<List<SysConfigResponse>> GetAllAsync()
|
|
{
|
|
var configs = await repo.GetAllAsync();
|
|
return configs.Select(ToResponse).ToList();
|
|
}
|
|
|
|
public async Task<SysConfigResponse?> GetByKeyAsync(string key)
|
|
{
|
|
var config = await repo.GetByKeyAsync(key);
|
|
return config is null ? null : ToResponse(config);
|
|
}
|
|
|
|
public async Task<SysConfigResponse> SetAsync(string key, string value, Guid userId, CancellationToken ct = default)
|
|
{
|
|
ValidateValue(key, value);
|
|
|
|
var config = new Models.SysConfig
|
|
{
|
|
Key = key,
|
|
Value = value,
|
|
UpdatedAt = DateTime.Now,
|
|
UpdatedBy = userId
|
|
};
|
|
|
|
await uow.BeginAsync(ct);
|
|
try
|
|
{
|
|
await repo.UpsertAsync(config);
|
|
await uow.CommitAsync(ct);
|
|
}
|
|
catch { await uow.RollbackAsync(ct); throw; }
|
|
|
|
var saved = await repo.GetByKeyAsync(key);
|
|
return ToResponse(saved!);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the current InvoiceCreationMode, defaulting to ModeB if not configured.
|
|
/// ModeA = invoice auto-created on ShopPO confirmation.
|
|
/// ModeB = invoice created as a separate explicit step.
|
|
/// </summary>
|
|
public async Task<InvoiceCreationMode> GetInvoiceCreationModeAsync()
|
|
{
|
|
var config = await repo.GetByKeyAsync(KeyInvoiceCreationMode);
|
|
if (config is null) return InvoiceCreationMode.ModeB;
|
|
return Enum.TryParse<InvoiceCreationMode>(config.Value, out var mode) ? mode : InvoiceCreationMode.ModeB;
|
|
}
|
|
|
|
public async Task<bool> GetSerialNumberTrackingEnabledAsync() => await GetBoolAsync(KeySerialNumberTrackingEnabled);
|
|
public async Task<bool> GetBatchTrackingEnabledAsync() => await GetBoolAsync(KeyBatchTrackingEnabled);
|
|
public async Task<bool> GetExpiryDateTrackingEnabledAsync() => await GetBoolAsync(KeyExpiryDateTrackingEnabled);
|
|
public async Task<bool> GetWarrantyTrackingEnabledAsync() => await GetBoolAsync(KeyWarrantyTrackingEnabled);
|
|
public async Task<bool> GetCustomWarrantyOverrideEnabledAsync() => await GetBoolAsync(KeyCustomWarrantyOverrideEnabled);
|
|
|
|
public async Task<int> GetDefaultWarrantyPeriodDaysAsync()
|
|
{
|
|
var config = await repo.GetByKeyAsync(KeyDefaultWarrantyPeriodDays);
|
|
return config is not null && int.TryParse(config.Value, out var days) ? days : 0;
|
|
}
|
|
|
|
private async Task<bool> GetBoolAsync(string key)
|
|
{
|
|
var config = await repo.GetByKeyAsync(key);
|
|
return config is not null && bool.TryParse(config.Value, out var enabled) && enabled;
|
|
}
|
|
|
|
private static void ValidateValue(string key, string value)
|
|
{
|
|
if (key == KeyInvoiceCreationMode && !Enum.TryParse<InvoiceCreationMode>(value, out _))
|
|
throw new InvalidOperationException(
|
|
$"Invalid value '{value}' for '{key}'. Allowed values: {string.Join(", ", Enum.GetNames<InvoiceCreationMode>())}.");
|
|
|
|
if (BooleanFeatureKeys.Contains(key) && !bool.TryParse(value, out _))
|
|
throw new InvalidOperationException($"Invalid value '{value}' for '{key}'. Allowed values: true, false.");
|
|
|
|
if (key == KeyDefaultWarrantyPeriodDays && (!int.TryParse(value, out var days) || days < 0))
|
|
throw new InvalidOperationException($"Invalid value '{value}' for '{key}'. Must be a non-negative integer.");
|
|
}
|
|
|
|
private static SysConfigResponse ToResponse(Models.SysConfig c) =>
|
|
new(c.Key, c.Value, c.UpdatedAt, c.UpdatedBy);
|
|
}
|