using Microsoft.Extensions.Logging; using Quadarax.Application.QLiberace.Base.Dtos; using Quadarax.Application.QLiberace.Base.Entities; using Quadarax.Application.QLiberace.Base.Repositories; using Quadarax.Application.QLiberace.Common; using Quadarax.Application.QLiberace.Common.Attributes; using Quadarax.Application.QLiberace.Common.Settings; using Quadarax.Foundation.Core.Business; using Quadarax.Foundation.Core.Data; using Quadarax.Foundation.Core.Data.Interface; using Quadarax.Foundation.Core.Data.Interface.Domain; using Quadarax.Foundation.Core.Data.Interface.Entity.Dto; using Quadarax.Foundation.Core.Logging; using Quadarax.Foundation.Core.Reflection; namespace Quadarax.Application.QLiberace.Base.Services { public class SettingsService : AbstractRepositoryService { #region *** Constructor *** public SettingsService(RepoSetting repository, IContext currentContext, IQLogger logger) : base(repository, currentContext, logger) { //TODO: add enable (field) functionality in GetSettings, GetSettingsValue, GetSettingsValues, GetSettingValueAsString //TODO: add method to enable/disable/status setting value } #endregion #region *** Public Operations *** public ResultPlain CreateSettings(ModuleSetting settings) where TSettings : ModuleSetting { if (settings == null) throw new ArgumentNullException(nameof(settings)); return TryCatchBlock(() => { var attrs = AttributeQuery.FindAll(typeof(TSettings), true); if (attrs.Length == 0) throw new InvalidOperationException( $"ModuleAttribute is not defined on class '{typeof(TSettings).Name}'."); if (attrs.Length > 1) throw new InvalidOperationException( "ModuleAttribute is defined on more than one ModuleSetting class."); var settingsFlat = settings.GetData(); foreach (var flat in settingsFlat) { var setting = Repository.New(); setting.Code = flat.Item1; setting.ModuleCode = attrs[0].ModuleCode; setting.IsEnabled = true; setting.Description = string.Empty; setting.ValueTypeQualified = flat.Item2; setting.Value = flat.Item3?.ToString(); Repository.Set(setting); } return new ResultPlain(); }); } public ResultValueDto GetSettings(string moduleCode) where TSettings : ModuleSetting, new() { if (string.IsNullOrEmpty(moduleCode)) throw new ArgumentNullException(nameof(moduleCode)); return TryCatchBlock(() => { if (!Repository.QueryModule(moduleCode, Paging.NoPaging()).Any()) throw ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.SettingsNotFoundForModuleCode, moduleCode); var settingDto = Activator.CreateInstance(); if (settingDto == null) throw new ArgumentNullException(nameof(settingDto)); var settings = Repository.QueryModule(moduleCode,Paging.NoPaging()); settingDto.SetData(settings.Select(x=>new Tuple(x.Code,x.ValueTypeQualified,x.GetTypedValue()))); return new ResultValueDto(settingDto); }); } public ResultValueDto GetSettingsValue(string moduleCode, string valueCode) { if (string.IsNullOrEmpty(moduleCode)) throw new ArgumentNullException(nameof(moduleCode)); if (string.IsNullOrEmpty(valueCode)) throw new ArgumentNullException(nameof(valueCode)); return TryCatchBlock(() => { var settings = GetSettings(moduleCode, valueCode); if (settings == null) throw ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.SettingsNotFoundCode, valueCode, moduleCode); return new ResultValueDto(settings.GetTypedValue()); }); } public ResultBoolDto ExistsSettings(string moduleCode) { if (string.IsNullOrEmpty(moduleCode)) throw new ArgumentNullException(nameof(moduleCode)); return TryCatchBlock(() => { var result = Repository.QueryModule(moduleCode, Paging.NoPaging()).Any(); return new ResultBoolDto(result); }); } public ResultBoolDto ExistsSettingsValue(string moduleCode, string valueCode) { if (string.IsNullOrEmpty(moduleCode)) throw new ArgumentNullException(nameof(moduleCode)); if (string.IsNullOrEmpty(valueCode)) throw new ArgumentNullException(nameof(valueCode)); return TryCatchBlock(() => { var result = Repository.QueryModule(moduleCode, Paging.NoPaging()).Any(x => x.Code == valueCode); return new ResultBoolDto(result); }); } public ResultPlain AddSettingsValue(string moduleCode, string valueCode, string valueDescription, object value) { if (string.IsNullOrEmpty(moduleCode)) throw new ArgumentNullException(nameof(moduleCode)); if (string.IsNullOrEmpty(valueCode)) throw new ArgumentNullException(nameof(valueCode)); return TryCatchBlock(() => { var exists = ExistsSettingsValue(moduleCode, valueCode); if (!exists.IsSuccess) return new ResultPlain(exists.Errors); if (exists.Value) throw ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.SettingsAlreadyExistsCode, valueCode, moduleCode); var settings = Repository.New(); settings.ModuleCode = moduleCode; settings.Code = valueCode; settings.Description = valueDescription; settings.Value = value?.ToString(); var settingsValueTypeQualified = typeof(TValue).FullName; if (settingsValueTypeQualified != null) settings.ValueTypeQualified = settingsValueTypeQualified; settings.IsEnabled = true; //Repository.Commit(); return new ResultPlain(); }); } public ResultPlain UpdateSettings(ModuleSetting settings) where TSettings : ModuleSetting { if (settings == null) throw new ArgumentNullException(nameof(settings)); return TryCatchBlock(() => { var attrs = AttributeQuery.FindAll(typeof(TSettings), true); if (attrs.Length == 0) throw new InvalidOperationException( $"ModuleAttribute is not defined on class '{typeof(TSettings).Name}'."); if (attrs.Length > 1) throw new InvalidOperationException( "ModuleAttribute is defined on more than one ModuleSetting class."); if (!ExistsSettings(attrs[0].ModuleCode).Value) throw ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.SettingsNotFoundForModuleCode, attrs[0].ModuleCode); var settingsFlat = settings.GetData(); foreach (var flat in settingsFlat) { var setting = GetSettings(attrs[0].ModuleCode, flat.Item1); if (setting == null) throw ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.SettingsNotFoundCode, flat.Item1, attrs[0].ModuleCode); setting.Value = GetSettingValueAsString(flat.Item3); Repository.Set(setting); } //Repository.Commit(); return new ResultPlain(); }); } public ResultPlain UpdateSettingsValue(string moduleCode, string valueCode, object value) { if (string.IsNullOrEmpty(moduleCode)) throw new ArgumentNullException(nameof(moduleCode)); if (string.IsNullOrEmpty(valueCode)) throw new ArgumentNullException(nameof(valueCode)); return TryCatchBlock(() => { var exists = ExistsSettingsValue(moduleCode, valueCode); if (!exists.IsSuccess) return new ResultPlain(exists.Errors); if (!exists.Value) throw ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.SettingsNotFoundCode, valueCode, moduleCode); var settings = Repository.Get(moduleCode, valueCode); if (settings==null) throw ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.SettingsNotFoundCode, valueCode, moduleCode); settings.Value = GetSettingValueAsString(value); Repository.Set(settings); //Repository.Commit(); return new ResultPlain(); }); } public ResultPlain AddOrUpdateSettingsValue(string moduleCode, string valueCode, object value) { return AddOrUpdateSettingsValue(moduleCode, valueCode, value, string.Empty); } public ResultPlain AddOrUpdateSettingsValue(string moduleCode, string valueCode, object value, string valueDescription) { if (string.IsNullOrEmpty(moduleCode)) throw new ArgumentNullException(nameof(moduleCode)); if (string.IsNullOrEmpty(valueCode)) throw new ArgumentNullException(nameof(valueCode)); return TryCatchBlock(() => { var exists = ExistsSettingsValue(moduleCode, valueCode); if (!exists.IsSuccess) return new ResultPlain(exists.Errors); if (exists.Value) { return UpdateSettingsValue(moduleCode, valueCode, value); } else { return AddSettingsValue(moduleCode, valueCode, valueDescription, value); } }); } public ResultSettingsValuesListDto GetSettingsValues(string moduleCode, IPaging paging) { if (string.IsNullOrEmpty(moduleCode)) throw new ArgumentNullException(nameof(moduleCode)); return TryCatchBlock(() => { var result = Repository.QueryModule(moduleCode, paging) .ToDictionary(x => x.Code, y => y.GetTypedValue()); return new ResultSettingsValuesListDto(result); }); } #endregion #region ** Private Operations *** private Setting? GetSettings(string moduleCode, string valueCode) { var settings = Repository.Get(moduleCode, valueCode); return settings; } private string? GetSettingValueAsString(object? value) { if (value == null) return null; if (value is DateTime time) { return time.ToString("O"); } return value.ToString(); } #endregion } }