diff --git a/Distribution/Features/SysConfig/SysConfigController.cs b/Distribution/Features/SysConfig/SysConfigController.cs index a2571bc..bfacd85 100644 --- a/Distribution/Features/SysConfig/SysConfigController.cs +++ b/Distribution/Features/SysConfig/SysConfigController.cs @@ -42,10 +42,11 @@ public class SysConfigController(SysConfigService service, ICurrentUserService c [HttpPut("{key}")] public async Task Set(string key, SetSysConfigRequest request, CancellationToken ct) { - var userId = currentUser.UserId ?? throw new UnauthorizedAccessException(); + var userId = currentUser.UserId ?? request.UserId; + if (userId is null) return BadRequest(new { error = "UserId is required while auth is unavailable" }); try { - var result = await service.SetAsync(key, request.Value, userId, ct); + var result = await service.SetAsync(key, request.Value, userId.Value, ct); return Ok(result); } catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } diff --git a/Distribution/Features/SysConfig/SysConfigDTOs.cs b/Distribution/Features/SysConfig/SysConfigDTOs.cs index 6084673..2907521 100644 --- a/Distribution/Features/SysConfig/SysConfigDTOs.cs +++ b/Distribution/Features/SysConfig/SysConfigDTOs.cs @@ -4,6 +4,6 @@ namespace Distribution.Features.SysConfig; public record SysConfigResponse(string Key, string Value, DateTime UpdatedAt, Guid? UpdatedBy); -public record SetSysConfigRequest(string Value); +public record SetSysConfigRequest(string Value, Guid? UserId); public record SetInvoiceCreationModeRequest(InvoiceCreationMode Mode); diff --git a/Distribution/Features/SysConfig/SysConfigService.cs b/Distribution/Features/SysConfig/SysConfigService.cs index 397d53c..a47bca1 100644 --- a/Distribution/Features/SysConfig/SysConfigService.cs +++ b/Distribution/Features/SysConfig/SysConfigService.cs @@ -7,6 +7,22 @@ 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> GetAllAsync() { var configs = await repo.GetAllAsync(); @@ -55,11 +71,35 @@ public class SysConfigService(ISysConfigRepository repo, IUnitOfWork uow) return Enum.TryParse(config.Value, out var mode) ? mode : InvoiceCreationMode.ModeB; } + public async Task GetSerialNumberTrackingEnabledAsync() => await GetBoolAsync(KeySerialNumberTrackingEnabled); + public async Task GetBatchTrackingEnabledAsync() => await GetBoolAsync(KeyBatchTrackingEnabled); + public async Task GetExpiryDateTrackingEnabledAsync() => await GetBoolAsync(KeyExpiryDateTrackingEnabled); + public async Task GetWarrantyTrackingEnabledAsync() => await GetBoolAsync(KeyWarrantyTrackingEnabled); + public async Task GetCustomWarrantyOverrideEnabledAsync() => await GetBoolAsync(KeyCustomWarrantyOverrideEnabled); + + public async Task GetDefaultWarrantyPeriodDaysAsync() + { + var config = await repo.GetByKeyAsync(KeyDefaultWarrantyPeriodDays); + return config is not null && int.TryParse(config.Value, out var days) ? days : 0; + } + + private async Task 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(value, out _)) throw new InvalidOperationException( $"Invalid value '{value}' for '{key}'. Allowed values: {string.Join(", ", Enum.GetNames())}."); + + 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) =>