فهرست منبع

add tenant related settings, fix tests

Dalibor Votruba 3 سال پیش
والد
کامیت
2475f61f38
33فایلهای تغییر یافته به همراه293 افزوده شده و 87 حذف شده
  1. 31 0
      Common/qdr.app.qlbrc.common/Domain/QlbrcContext.cs
  2. 1 1
      Common/qdr.app.qlbrc.common/Entities/Base/QlbrcEntity.cs
  3. 2 2
      Common/qdr.app.qlbrc.common/Entities/Base/QlbrcEntityTenant.cs
  4. 1 1
      Common/qdr.app.qlbrc.common/Entities/Base/QlbrcEntityTracked.cs
  5. 0 15
      Common/qdr.app.qlbrc.common/Entities/Base/QlbrcEntityTrackedWithoutId.cs
  6. 0 8
      Common/qdr.app.qlbrc.common/Entities/Base/QlbrcEntityWithoutId.cs
  7. 4 3
      Common/qdr.app.qlbrc.common/Repositories/QlbrcRepository.cs
  8. 43 0
      Common/qdr.app.qlbrc.common/Repositories/QlbrcTenantRepository.cs
  9. 48 0
      Common/qdr.app.qlbrc.common/Repositories/QlbrcTracedTenantRepository.cs
  10. 6 6
      Common/qdr.app.qlbrc.common/Repositories/QlbrcTrackedRepository.cs
  11. 5 5
      Common/qdr.fnd.core.business/AbstractMultiRepositoryService.cs
  12. 2 1
      Common/qdr.fnd.core.business/AbstractRepositoryService.cs
  13. 16 11
      Common/qdr.fnd.core.business/AbstractService.cs
  14. 10 0
      Common/qdr.fnd.core.data.itfc/Domain/IContext.cs
  15. 2 0
      Common/qdr.fnd.core.data.itfc/Domain/IUnitOfWork.cs
  16. 19 4
      Common/qdr.fnd.core.data/Domain/UnitOfWork.cs
  17. 7 0
      Common/qdr.fnd.core.data/Repository/EntityRepository.cs
  18. 2 2
      Modules/qdr.app.qlbrc.base/Entities/Setting.cs
  19. 1 1
      Modules/qdr.app.qlbrc.base/Entities/Tenant.cs
  20. 1 1
      Modules/qdr.app.qlbrc.base/Entities/User.cs
  21. 23 8
      Modules/qdr.app.qlbrc.base/Repositories/RepoSetting.cs
  22. 5 3
      Modules/qdr.app.qlbrc.base/Services/SettingsService.cs
  23. 6 1
      Modules/qdr.app.qlbrc.base/qdr.app.qlbrc.base.csproj
  24. 3 2
      Tests/qdr.app.qlbrc.base.Tests/Entities/Base/BaseDaoTest.cs
  25. 1 2
      Tests/qdr.app.qlbrc.base.Tests/Entities/SettingTest.cs
  26. 1 1
      Tests/qdr.app.qlbrc.base.Tests/Entities/TenantTest.cs
  27. 1 1
      Tests/qdr.app.qlbrc.base.Tests/Entities/UserTest.cs
  28. 26 0
      Tests/qdr.app.qlbrc.base.Tests/Services/Fakes/ContextFake.cs
  29. 1 1
      Tests/qdr.app.qlbrc.base.Tests/Services/Fakes/LoggerFake.cs
  30. 18 2
      Tests/qdr.app.qlbrc.base.Tests/Services/SettingsServiceTest.cs
  31. 3 2
      Tests/qdr.app.qlbrc.common.Tests/Repositories/CommonRepositoryTest.cs
  32. 1 1
      Tests/qdr.app.qlbrc.common.Tests/Repositories/Fakes/TestTenantTrackedDao.cs
  33. 3 2
      Tests/qdr.app.qlbrc.common.Tests/Repositories/Fakes/TestTenantTrackedRepo.cs

+ 31 - 0
Common/qdr.app.qlbrc.common/Domain/QlbrcContext.cs

@@ -0,0 +1,31 @@
+using System.Security.Principal;
+using Quadarax.Foundation.Core.Data.Interface.Domain;
+
+namespace Quadarax.Application.QLiberace.Common.Domain
+{
+    public class QlbrcContext : IContext
+    {
+        public IPrincipal CurrentUser { get; }
+        public string? TenantCode { get; }
+        public long? TenantId { get; }
+
+        public QlbrcContext(IPrincipal? currentUser, string? tenantCode, long? tenantId)
+        {
+            if (currentUser == null)
+            {
+                var genericIdentity = new GenericIdentity("genericIdentity");
+                currentUser = new GenericPrincipal(genericIdentity, Array.Empty<string>());
+            }
+            CurrentUser = currentUser;
+            TenantCode = tenantCode;
+            TenantId = tenantId;
+        }
+
+
+        public TContext GetContext<TContext>() where TContext : IContext
+        {
+            return (TContext)(IContext)this;
+        }
+
+    }
+}

+ 1 - 1
Common/qdr.app.qlbrc.common/Entities/Base/QlbrcEntityWithId.cs → Common/qdr.app.qlbrc.common/Entities/Base/QlbrcEntity.cs

@@ -5,7 +5,7 @@ using Quadarax.Foundation.Core.Data.Entity;
 
 namespace Quadarax.Application.QLiberace.Common.Entities.Base;
 
-public abstract  class QlbrcEntityWithId : Entity<long>, IIdentifier
+public abstract  class QlbrcEntity : Entity<long>, IIdentifier
 {
     [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
     [Key]

+ 2 - 2
Common/qdr.app.qlbrc.common/Entities/Base/QlbrcEntityTenantWithId.cs → Common/qdr.app.qlbrc.common/Entities/Base/QlbrcEntityTenant.cs

@@ -3,9 +3,9 @@ using Quadarax.Application.QLiberace.Base.Entities.Base;
 
 namespace Quadarax.Application.QLiberace.Common.Entities.Base
 {
-    public abstract class QlbrcEntityTenantWithId : QlbrcEntityTrackedWithId, ITenant
+    public abstract class QlbrcEntityTenant : QlbrcEntityTracked, ITenant
     {
         [ForeignKey("FK_Tenant_Id")]
-        public long TenantId { get; protected set; }
+        public long TenantId { get; set; }
     }
 }

+ 1 - 1
Common/qdr.app.qlbrc.common/Entities/Base/QlbrcEntityTrackedWithId.cs → Common/qdr.app.qlbrc.common/Entities/Base/QlbrcEntityTracked.cs

@@ -3,7 +3,7 @@ using System.ComponentModel.DataAnnotations.Schema;
 
 namespace Quadarax.Application.QLiberace.Common.Entities.Base
 {
-    public abstract class QlbrcEntityTrackedWithId : QlbrcEntityWithId, ITracked
+    public abstract class QlbrcEntityTracked : QlbrcEntity, ITracked
     {
         [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
         [Required]

+ 0 - 15
Common/qdr.app.qlbrc.common/Entities/Base/QlbrcEntityTrackedWithoutId.cs

@@ -1,15 +0,0 @@
-using System.ComponentModel.DataAnnotations.Schema;
-using System.ComponentModel.DataAnnotations;
-
-namespace Quadarax.Application.QLiberace.Common.Entities.Base
-{
-    public abstract class QlbrcEntityTrackedWithoutId: QlbrcEntityWithId, ITracked
-    {
-        [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
-        [Required]
-        public DateTime Created { get; protected set; }
-        public DateTime? Modified { get; protected set;}
-        [MaxLength(100)]
-        public string? Modifier { get; protected set;}
-    }
-}

+ 0 - 8
Common/qdr.app.qlbrc.common/Entities/Base/QlbrcEntityWithoutId.cs

@@ -1,8 +0,0 @@
-using Quadarax.Foundation.Core.Data.Entity;
-
-namespace Quadarax.Application.QLiberace.Common.Entities.Base
-{
-    public abstract class QlbrcEntityWithoutId : Entity<NoKey> , IEntity
-    {
-    }
-}

+ 4 - 3
Common/qdr.app.qlbrc.common/Repositories/QlbrcRepository.cs

@@ -1,13 +1,14 @@
-using Quadarax.Application.QLiberace.Common.Entities.Base;
+using Quadarax.Application.QLiberace.Common.Domain;
+using Quadarax.Application.QLiberace.Common.Entities.Base;
 using Quadarax.Foundation.Core.Data.Domain;
 using Quadarax.Foundation.Core.Data.Interface.Domain;
 using Quadarax.Foundation.Core.Data.Repository;
 
 namespace Quadarax.Application.QLiberace.Common.Repositories
 {
-    public abstract class QlbrcRepository<TEntity> : EntityRepository<long, TEntity> where TEntity : QlbrcEntityWithId, new()
+    public abstract class QlbrcRepository<TEntity> : EntityRepository<long, TEntity> where TEntity : QlbrcEntity, new()
     {
-        protected QlbrcRepository(IUnitOfWork<IDataDomain> unitOfWork) : base(unitOfWork)
+        protected QlbrcRepository(IUnitOfWork<IDataDomain> unitOfWork, QlbrcContext operationContext) : base(unitOfWork, operationContext)
         {
         }
     }

+ 43 - 0
Common/qdr.app.qlbrc.common/Repositories/QlbrcTenantRepository.cs

@@ -0,0 +1,43 @@
+using Quadarax.Application.QLiberace.Common.Domain;
+using Quadarax.Application.QLiberace.Common.Entities.Base;
+using Quadarax.Foundation.Core.Data;
+using Quadarax.Foundation.Core.Data.Domain;
+using Quadarax.Foundation.Core.Data.Interface;
+using Quadarax.Foundation.Core.Data.Interface.Domain;
+using Quadarax.Foundation.Core.Data.Extensions;
+
+namespace Quadarax.Application.QLiberace.Common.Repositories
+{
+    public abstract class QlbrcTenantRepository<TEntity> :QlbrcRepository<TEntity> where TEntity : QlbrcEntityTenant, new()
+    {
+        protected long? TenantId => OperationContext.GetContext<QlbrcContext>().TenantId;
+
+        protected QlbrcTenantRepository(IUnitOfWork<IDataDomain> unitOfWork, QlbrcContext operationContext) : base(unitOfWork, operationContext)
+        {
+        }
+
+        public override IQueryable<TEntity> Query(IPaging paging,bool usingUncommited=false)
+        {
+            return base.Query(paging, usingUncommited).Where(x=>Equals(x.TenantId == TenantId));
+        }
+
+        public override TEntity Get(long id)
+        {
+            return Query(new Paging()).MultiInclude(DefaultIncludes.ToArray()).FirstOrDefault(x => Equals(x.Id, id) && Equals(x.TenantId,TenantId))!;
+        }
+
+        public override IQueryable<TEntity> Get(IEnumerable<long> ids)
+        {
+            return Query(new Paging()).Where(x => ids.Contains(x.Id) && Equals(x.TenantId,TenantId));
+        }
+
+        public override TEntity New()
+        {
+            var entity = base.New();
+            entity.TenantId = TenantId.GetValueOrDefault();
+            return entity;
+        }
+
+
+    }
+}

+ 48 - 0
Common/qdr.app.qlbrc.common/Repositories/QlbrcTracedTenantRepository.cs

@@ -0,0 +1,48 @@
+using System.Diagnostics;
+using Quadarax.Application.QLiberace.Common.Domain;
+using Quadarax.Application.QLiberace.Common.Entities.Base;
+using Quadarax.Foundation.Core.Data;
+using Quadarax.Foundation.Core.Data.Domain;
+using Quadarax.Foundation.Core.Data.Extensions;
+using Quadarax.Foundation.Core.Data.Interface;
+using Quadarax.Foundation.Core.Data.Interface.Domain;
+
+namespace Quadarax.Application.QLiberace.Common.Repositories
+{
+    public abstract class QlbrcTenantTrackedRepository<TEntity> :QlbrcTrackedRepository<TEntity> where TEntity : QlbrcEntityTenant, new()
+    {
+        
+        protected long? TenantId => OperationContext.GetContext<QlbrcContext>().TenantId;
+
+        protected QlbrcTenantTrackedRepository(IUnitOfWork<IDataDomain> unitOfWork, QlbrcContext operationContext) : base(unitOfWork, operationContext)
+        {
+        }
+        
+        public override IQueryable<TEntity> Query(IPaging paging,bool usingUncommited=false)
+        {
+            var result = base.Query(paging, usingUncommited).Where(x => Equals(x.TenantId ,TenantId));
+#if DEBUG
+            Debug.WriteLine($"Repo '{GetType().Name}' Query returns {result.Count()} rows.");
+#endif
+            return result;
+        }
+
+        public override TEntity Get(long id)
+        {
+            return Query(new Paging()).MultiInclude(DefaultIncludes.ToArray()).FirstOrDefault(x => Equals(x.Id, id) && Equals(x.TenantId,TenantId))!;
+        }
+
+        public override IQueryable<TEntity> Get(IEnumerable<long> ids)
+        {
+            return Query(new Paging()).Where(x => ids.Contains(x.Id) && Equals(x.TenantId,TenantId));
+        }
+
+        public override TEntity New()
+        {
+            var entity = base.New();
+            entity.TenantId = TenantId.GetValueOrDefault();
+            return entity;
+        }
+
+    }
+}

+ 6 - 6
Common/qdr.app.qlbrc.common/Repositories/QlbrcTrackedRepository.cs

@@ -1,15 +1,14 @@
-using Quadarax.Application.QLiberace.Common.Entities.Base;
+using Quadarax.Application.QLiberace.Common.Domain;
+using Quadarax.Application.QLiberace.Common.Entities.Base;
 using Quadarax.Foundation.Core.Data.Domain;
 using Quadarax.Foundation.Core.Data.Interface.Domain;
 
 namespace Quadarax.Application.QLiberace.Common.Repositories
 {
-    public abstract class QlbrcTrackedRepository<TEntityTracked> : QlbrcRepository<TEntityTracked> where TEntityTracked : QlbrcEntityTrackedWithId, new()
+    public abstract class QlbrcTrackedRepository<TEntityTracked> : QlbrcRepository<TEntityTracked> where TEntityTracked : QlbrcEntityTracked, new()
     {
-        private string _modifier;
-        protected QlbrcTrackedRepository(IUnitOfWork<IDataDomain> unitOfWork, string modifier) : base(unitOfWork)
+        protected QlbrcTrackedRepository(IUnitOfWork<IDataDomain> unitOfWork, QlbrcContext operationContext) : base(unitOfWork, operationContext)
         {
-            _modifier = modifier;
         }
 
         public override TEntityTracked New()
@@ -23,8 +22,9 @@ namespace Quadarax.Application.QLiberace.Common.Repositories
         {
             var dao = base.Set(entity);
             dao.Modified = DateTime.Now;
-            dao.Modifier = _modifier;
+            dao.Modifier = OperationContext.GetContext<QlbrcContext>().CurrentUser.Identity?.Name;
             return dao;
         }
+
     }
 }

+ 5 - 5
Common/qdr.fnd.core.business/AbstractMultiRepositoryService.cs

@@ -1,6 +1,6 @@
 using System;
-using System.Security.Principal;
 using Microsoft.Extensions.Logging;
+using Quadarax.Foundation.Core.Data.Interface.Domain;
 using Quadarax.Foundation.Core.Data.Interface.Repository;
 
 namespace Quadarax.Foundation.Core.Business
@@ -12,7 +12,7 @@ namespace Quadarax.Foundation.Core.Business
         protected TRepository1 Repository1 { get; }
         protected TRepository2 Repository2 { get; }
 
-        protected AbstractMultiRepositoryService(TRepository1 repository1, TRepository2 repository2,IPrincipal currentPrincipal,  ILoggerFactory logger) : base(currentPrincipal, logger)
+        protected AbstractMultiRepositoryService(TRepository1 repository1, TRepository2 repository2,IContext currentContext, ILoggerFactory logger) : base(currentContext, logger)
         {
             Repository1 = repository1 ?? throw new ArgumentNullException(nameof(repository1));
             Repository2 = repository2 ?? throw new ArgumentNullException(nameof(repository2));
@@ -29,7 +29,7 @@ namespace Quadarax.Foundation.Core.Business
         protected TRepository2 Repository2 { get; }
         protected TRepository3 Repository3 { get; }
 
-        protected AbstractMultiRepositoryService(TRepository1 repository1, TRepository2 repository2, TRepository3 repository3,IPrincipal currentPrincipal, ILoggerFactory logger) : base(currentPrincipal, logger)
+        protected AbstractMultiRepositoryService(TRepository1 repository1, TRepository2 repository2, TRepository3 repository3,IContext currentContext, ILoggerFactory logger) : base(currentContext, logger)
         {
             Repository1 = repository1 ?? throw new ArgumentNullException(nameof(repository1));
             Repository2 = repository2 ?? throw new ArgumentNullException(nameof(repository2));
@@ -48,7 +48,7 @@ namespace Quadarax.Foundation.Core.Business
         protected TRepository3 Repository3 { get; }
         protected TRepository4 Repository4 { get; }
 
-        protected AbstractMultiRepositoryService(TRepository1 repository1, TRepository2 repository2, TRepository3 repository3,TRepository4 repository4, IPrincipal currentPrincipal, ILoggerFactory logger) : base(currentPrincipal, logger)
+        protected AbstractMultiRepositoryService(TRepository1 repository1, TRepository2 repository2, TRepository3 repository3,TRepository4 repository4, IContext currentContext, ILoggerFactory logger) : base(currentContext, logger)
         {
             Repository1 = repository1 ?? throw new ArgumentNullException(nameof(repository1));
             Repository2 = repository2 ?? throw new ArgumentNullException(nameof(repository2));
@@ -71,7 +71,7 @@ namespace Quadarax.Foundation.Core.Business
         protected TRepository4 Repository4 { get; }
         protected TRepository5 Repository5 { get; }
 
-        protected AbstractMultiRepositoryService(TRepository1 repository1, TRepository2 repository2, TRepository3 repository3,TRepository4 repository4,TRepository5 repository5,IPrincipal currentPrincipal, ILoggerFactory logger) : base(currentPrincipal, logger)
+        protected AbstractMultiRepositoryService(TRepository1 repository1, TRepository2 repository2, TRepository3 repository3,TRepository4 repository4,TRepository5 repository5,IContext currentContext, ILoggerFactory logger) : base(currentContext, logger)
         {
             Repository1 = repository1 ?? throw new ArgumentNullException(nameof(repository1));
             Repository2 = repository2 ?? throw new ArgumentNullException(nameof(repository2));

+ 2 - 1
Common/qdr.fnd.core.business/AbstractRepositoryService.cs

@@ -2,6 +2,7 @@
 using System.Security.Principal;
 using Microsoft.Extensions.Logging;
 using NLog;
+using Quadarax.Foundation.Core.Data.Interface.Domain;
 using Quadarax.Foundation.Core.Data.Interface.Repository;
 
 namespace Quadarax.Foundation.Core.Business
@@ -10,7 +11,7 @@ namespace Quadarax.Foundation.Core.Business
     {
         protected TRepository Repository { get; }
 
-        protected AbstractRepositoryService(TRepository repository,IPrincipal currentPrincipal, ILoggerFactory logger) : base(currentPrincipal, logger)
+        protected AbstractRepositoryService(TRepository repository,IContext currentContext, ILoggerFactory logger) : base(currentContext, logger)
         {
             Repository = repository ?? throw new ArgumentNullException(nameof(repository));
         }

+ 16 - 11
Common/qdr.fnd.core.business/AbstractService.cs

@@ -1,11 +1,9 @@
 using System;
-using System.Linq;
-using System.Security.Principal;
 using Microsoft.Extensions.Logging;
 using Quadarax.Foundation.Core.Business.Interface;
+using Quadarax.Foundation.Core.Data.Interface.Domain;
 using Quadarax.Foundation.Core.Data.Interface.Entity;
 using Quadarax.Foundation.Core.Data.Interface.Entity.Dto;
-using Quadarax.Foundation.Core.Value;
 
 namespace Quadarax.Foundation.Core.Business
 {
@@ -13,20 +11,22 @@ namespace Quadarax.Foundation.Core.Business
     {
         #region *** Properties ***
         protected ILogger<AbstractService> Log { get; }
-        protected IPrincipal CurrentPrincipal { get; }
+        protected IContext CurrentContext { get; }
         #endregion
 
         #region *** Constructors ***
-        protected AbstractService(IPrincipal currentPrincipal, ILoggerFactory logger)
+        protected AbstractService(IContext currentContext, ILoggerFactory logger)
         {
+            CurrentContext = currentContext ?? throw new ArgumentNullException(nameof(currentContext));
+            if (logger == null)throw new ArgumentNullException(nameof(logger));
+            
             Log = logger.CreateLogger<AbstractService>();
 
-            if (currentPrincipal == null)
-            {
-                var genericIdentity = new GenericIdentity("genericIdentity");
-                currentPrincipal = new GenericPrincipal(genericIdentity, new string[] {});
-            }
-            CurrentPrincipal = currentPrincipal;
+            //if (currentContext == null)
+            //{
+            //    var genericIdentity = new GenericIdentity("genericIdentity");
+            //    currentContext = new GenericPrincipal(genericIdentity, new string[] {});
+            //}
             Log.LogTrace($"Service '{GetType().Name}' [Hash:{GetHashCode()}] initialized.");
         }
         #endregion
@@ -49,6 +49,11 @@ namespace Quadarax.Foundation.Core.Business
 
             return result;
         }
+
+        protected TContext GetContext<TContext>() where TContext : IContext
+        {
+            return (TContext)CurrentContext;
+        }
         #endregion
 
         #region *** Public Operations ***

+ 10 - 0
Common/qdr.fnd.core.data.itfc/Domain/IContext.cs

@@ -0,0 +1,10 @@
+using System.Security.Principal;
+
+namespace Quadarax.Foundation.Core.Data.Interface.Domain
+{
+    public interface IContext
+    {
+        IPrincipal CurrentUser { get; }
+        TContext GetContext<TContext>() where TContext : IContext;
+    }
+}

+ 2 - 0
Common/qdr.fnd.core.data.itfc/Domain/IUnitOfWork.cs

@@ -4,6 +4,8 @@ namespace Quadarax.Foundation.Core.Data.Interface.Domain
 {
     public interface IUnitOfWork<TDomainContext> : IDisposable where TDomainContext : IDomain
     {
+        Guid Stamp { get; }
+        int CtxHash { get; }
         TDomainContext Context { get;  }
         void Commit();
 

+ 19 - 4
Common/qdr.fnd.core.data/Domain/UnitOfWork.cs

@@ -1,4 +1,6 @@
-using Quadarax.Foundation.Core.Data.Interface.Domain;
+using System;
+using System.Diagnostics;
+using Quadarax.Foundation.Core.Data.Interface.Domain;
 using Quadarax.Foundation.Core.Object;
 
 namespace Quadarax.Foundation.Core.Data.Domain
@@ -7,29 +9,42 @@ namespace Quadarax.Foundation.Core.Data.Domain
     {
 
         public TDomainContext Context { get; protected set; }
+        public Guid Stamp { get; protected set; }
+        public int CtxHash => Context.GetHashCode();
 
-        public UnitOfWork(IDomainContextResolver<TDomainContext> context)
+        public UnitOfWork(IDomainContextResolver<TDomainContext> context,Guid? customStamp = null)
         {
             Context = context.GetCurrent<TDomainContext>();
+            if (customStamp == null) 
+                customStamp = Guid.NewGuid();
+            Stamp = customStamp.GetValueOrDefault();
+            Debug.WriteLine($"UOW>>> {Stamp:D} [CTX:{CtxHash}] created");
+            
         }
 
-        public UnitOfWork(TDomainContext context)
+        public UnitOfWork(TDomainContext context, Guid? customStamp = null)
         {
             Context = context;
+            if (customStamp == null) 
+                customStamp = Guid.NewGuid();
+            Stamp = customStamp.GetValueOrDefault();
+            Debug.WriteLine($"UOW>>> {Stamp:D} [CTX:{CtxHash}] created");
         }
 
         public void Commit()
         {
             Context.Commit();
+            Debug.WriteLine($"UOW>>> {Stamp:D} [CTX:{CtxHash}] commited");
         }
 
         public IUnitOfWork<TCustomDomainContext> As<TCustomDomainContext>() where TCustomDomainContext : IDomain
         {
-            return new UnitOfWork<TCustomDomainContext>((TCustomDomainContext)(IDomain)Context);
+            return new UnitOfWork<TCustomDomainContext>((TCustomDomainContext)(IDomain)Context, Stamp);
         }
 
         protected override void OnDisposing()
         {
+            Debug.WriteLine($"UOW>>> {Stamp:D} [CTX:{CtxHash}] disposed");
             Context?.Rollback();
             Context = default;
         }

+ 7 - 0
Common/qdr.fnd.core.data/Repository/EntityRepository.cs

@@ -19,6 +19,8 @@ namespace Quadarax.Foundation.Core.Data.Repository
         private IUnitOfWork<IDataDomain> _unitOfWork;
         private DbSet<TEntity> DbSetInstance => _unitOfWork.Context.GetDbSet<DbSet<TEntity>>();
         protected IDataDomain Context => _unitOfWork.Context;
+        protected IContext OperationContext { get; }
+
         
         protected IList<string> DefaultIncludes { get; }
 
@@ -29,6 +31,11 @@ namespace Quadarax.Foundation.Core.Data.Repository
             //_dbSet = domain.GetDbSet<DbSet<TEntity>>();
         }
 
+        protected EntityRepository(IUnitOfWork<IDataDomain> unitOfWork, IContext currentOperationContext) : this(unitOfWork)
+        {
+            OperationContext = currentOperationContext ?? throw new ArgumentNullException(nameof(currentOperationContext));
+        }
+
         public virtual IQueryable<TEntity> Query(IPaging paging,bool usingUncommited=false)
         {
             if (paging == null) throw new ArgumentNullException(nameof(paging));

+ 2 - 2
Modules/qdr.app.qlbrc.base/Entities/Setting.cs

@@ -8,8 +8,8 @@ using Quadarax.Foundation.Core.Reflection;
 namespace Quadarax.Application.QLiberace.Base.Entities;
 
 [Table(Constants.Modules.Base.TblSetting,Schema = Constants.Modules.Base.Schema)]
-[Index("ModuleCode","Code", Name="IDX_CODE_MODULECODE", IsUnique = true )]
-public class Setting : QlbrcEntityTrackedWithoutId, IStructSetting
+[Index("TenantId", "ModuleCode","Code", Name="IDX_CODE_TENANTMODULECODE", IsUnique = true )]
+public class Setting : QlbrcEntityTenant, IStructSetting
 {
     #region *** Properties ***
     [ForeignKey("FK_Setting_Parent_Id")]

+ 1 - 1
Modules/qdr.app.qlbrc.base/Entities/Tenant.cs

@@ -8,7 +8,7 @@ namespace Quadarax.Application.QLiberace.Base.Entities
 {
     [Table(Constants.Modules.Base.TblTenant,Schema = Constants.Modules.Base.Schema)]
     [Index("Code", Name="IDX_TENANT_CODE", IsUnique = true )]
-    public class Tenant : QlbrcEntityTrackedWithId, IStructTenant
+    public class Tenant : QlbrcEntityTracked, IStructTenant
     {
         [MaxLength(20)]
         [Required(AllowEmptyStrings =false)]

+ 1 - 1
Modules/qdr.app.qlbrc.base/Entities/User.cs

@@ -9,7 +9,7 @@ namespace Quadarax.Application.QLiberace.Base.Entities
 {
     [Table(Constants.Modules.Base.TblUser,Schema = Constants.Modules.Base.Schema)]
     [Index("LoginName", Name="IDX_LOGIN_NAME", IsUnique = true )]
-    public class User : QlbrcEntityTrackedWithId, IStructUser
+    public class User : QlbrcEntityTracked, IStructUser
     {
         [MaxLength(100)]
         [Required(AllowEmptyStrings = false)]

+ 23 - 8
Modules/qdr.app.qlbrc.base/Repositories/RepoSetting.cs

@@ -1,20 +1,22 @@
-using Quadarax.Application.QLiberace.Base.Entities;
+using System.Diagnostics;
+using Quadarax.Application.QLiberace.Base.Entities;
+using Quadarax.Application.QLiberace.Common.Domain;
+using Quadarax.Application.QLiberace.Common.Repositories;
 using Quadarax.Foundation.Core.Data;
-using Quadarax.Foundation.Core.Data.Repository;
 using Quadarax.Foundation.Core.Data.Domain;
+using Quadarax.Foundation.Core.Data.Extensions;
 using Quadarax.Foundation.Core.Data.Interface;
 using Quadarax.Foundation.Core.Data.Interface.Domain;
 
 namespace Quadarax.Application.QLiberace.Base.Repositories
 {
-    public class RepoSetting : EntityRepository<long, Setting>
+    public class RepoSetting : QlbrcTenantTrackedRepository<Setting>
     {
-        public RepoSetting(IUnitOfWork<IDataDomain> unitOfWork) : base(unitOfWork)
+        
+        public RepoSetting(IUnitOfWork<IDataDomain> unitOfWork, QlbrcContext operationContext) : base(unitOfWork, operationContext)
         {
-            
         }
 
-
         public Setting? Get(string moduleCode, string valueCode)
         {
             var setting = QueryModule(moduleCode, Paging.NoPaging()).FirstOrDefault(x => x.Code == valueCode);
@@ -23,12 +25,22 @@ namespace Quadarax.Application.QLiberace.Base.Repositories
 
         public override IQueryable<Setting> Query(IPaging paging, bool usingUncommited = false)
         {
-            return base.Query(paging, usingUncommited).Where(x=>x.IsEnabled);
+            var result = base.Query(paging, usingUncommited).Where(x => x.IsEnabled);
+#if DEBUG
+                Debug.WriteLine($"Repo '{GetType().Name}' Query returns {result.Count()} rows.");
+#endif
+
+            return result;
         }
 
         public IQueryable<Setting> QueryModule(string moduleCode, IPaging paging)
         {
-            return Query(paging).Where(x => x.ModuleCode == moduleCode);
+            var result = Query(paging).Where(x => x.ModuleCode == moduleCode);
+#if DEBUG
+            Debug.WriteLine($"Repo '{GetType().Name}' Query returns {result.Count()} rows.");
+#endif
+
+            return result;
         }
 
         public string? GetValue(string moduleCode, string valueCode)
@@ -36,5 +48,8 @@ namespace Quadarax.Application.QLiberace.Base.Repositories
             var setting = QueryModule(moduleCode, Paging.NoPaging()).FirstOrDefault(x => x.Code == valueCode);
             return setting?.Value;
         }
+
     }
+
+    
 }

+ 5 - 3
Modules/qdr.app.qlbrc.base/Services/SettingsService.cs

@@ -1,5 +1,4 @@
-using System.Security.Principal;
-using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging;
 using Quadarax.Application.QLiberace.Base.Dtos;
 using Quadarax.Application.QLiberace.Base.Entities;
 using Quadarax.Application.QLiberace.Base.Repositories;
@@ -9,6 +8,7 @@ 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.Reflection;
 
@@ -17,8 +17,10 @@ namespace Quadarax.Application.QLiberace.Base.Services
     public class SettingsService : AbstractRepositoryService<RepoSetting>
     {
         #region *** Constructor ***
-        public SettingsService(RepoSetting repository, IPrincipal currentPrincipal, ILoggerFactory logger) : base(repository, currentPrincipal, logger)
+        public SettingsService(RepoSetting repository, IContext currentContext, ILoggerFactory 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
 

+ 6 - 1
Modules/qdr.app.qlbrc.base/qdr.app.qlbrc.base.csproj

@@ -7,6 +7,12 @@
     <RootNamespace>Quadarax.Application.QLiberace.Base</RootNamespace>
   </PropertyGroup>
 
+  <ItemGroup>
+    <Compile Remove="Entities\Base\**" />
+    <EmbeddedResource Remove="Entities\Base\**" />
+    <None Remove="Entities\Base\**" />
+  </ItemGroup>
+
   <ItemGroup>
     <ProjectReference Include="..\..\common\qdr.app.qlbrc.common\qdr.app.qlbrc.common.csproj" />
     <ProjectReference Include="..\..\Common\qdr.fnd.core.business\qdr.fnd.core.business.csproj" />
@@ -14,7 +20,6 @@
   </ItemGroup>
 
   <ItemGroup>
-    <Folder Include="Entities\Base\" />
     <Folder Include="Services\Result\" />
   </ItemGroup>
 

+ 3 - 2
Tests/qdr.app.qlbrc.base.Tests/Entities/Base/BaseDaoTest.cs

@@ -1,12 +1,13 @@
 using System.ComponentModel.DataAnnotations.Schema;
 using qdr.fnd.core.test;
-using Quadarax.Application.QLiberace.Base.Entities;
 using Quadarax.Application.QLiberace.Common.Entities.Base;
+using Quadarax.Foundation.Core.Data.Entity;
 using Quadarax.Foundation.Core.Reflection;
 
 namespace Quadarax.Application.QLiberace.Base.Tests.Entities.Base
 { 
-    public abstract class BaseDaoTest<TDao> : DaoTest<TDao, long> where TDao : QlbrcEntityWithId
+    public abstract class BaseDaoTest<TDao,TKey> : DaoTest<TDao, TKey> where TDao : Entity<TKey> 
+        where TKey : IEquatable<TKey>
     {
         protected void CheckHasTracked(string customMessage)
         {

+ 1 - 2
Tests/qdr.app.qlbrc.base.Tests/Entities/SettingTest.cs

@@ -1,11 +1,10 @@
-using Microsoft.EntityFrameworkCore.Metadata.Internal;
 using Quadarax.Application.QLiberace.Base.Entities;
 using Quadarax.Application.QLiberace.Base.Tests.Entities.Base;
 
 namespace Quadarax.Application.QLiberace.Base.Tests.Entities
 {
     [TestFixture(Category = "Dao")]
-    public class SettingTest : BaseDaoTest<Setting>
+    public class SettingTest : BaseDaoTest<Setting,long>
     {
        
         protected override void OnSetup()

+ 1 - 1
Tests/qdr.app.qlbrc.base.Tests/Entities/TenantTest.cs

@@ -5,7 +5,7 @@ using Quadarax.Application.QLiberace.Base.Tests.Entities.Base;
 namespace Quadarax.Application.QLiberace.Base.Tests.Entities
 {
     [TestFixture(Category = "Dao")]
-    public class TenantTest : BaseDaoTest<Tenant>
+    public class TenantTest : BaseDaoTest<Tenant, long>
     {
 
         [Test]

+ 1 - 1
Tests/qdr.app.qlbrc.base.Tests/Entities/UserTest.cs

@@ -4,7 +4,7 @@ using Quadarax.Application.QLiberace.Base.Tests.Entities.Base;
 namespace Quadarax.Application.QLiberace.Base.Tests.Entities
 {
     [TestFixture(Category = "Dao")]
-    public class UserTest : BaseDaoTest<User>
+    public class UserTest : BaseDaoTest<User, long>
     {
         
         [Test]

+ 26 - 0
Tests/qdr.app.qlbrc.base.Tests/Services/Fakes/ContextFake.cs

@@ -0,0 +1,26 @@
+using System.Security.Principal;
+using Quadarax.Foundation.Core.Data.Interface.Domain;
+
+namespace Quadarax.Application.QLiberace.Base.Tests.Services.Fakes
+{
+    public class ContextFake : IContext
+    {
+        public IPrincipal CurrentUser { get; }
+
+        public ContextFake()
+        {
+
+            var genericIdentity = new GenericIdentity("genericIdentity");
+            CurrentUser = new GenericPrincipal(genericIdentity, new string[] { });
+        }
+        public ContextFake(IPrincipal currentUser)
+        {
+            CurrentUser = currentUser;
+        }
+
+        public TContext GetContext<TContext>() where TContext : IContext
+        {
+            return (TContext)(IContext) this;
+        }
+    }
+}

+ 1 - 1
Tests/qdr.app.qlbrc.base.Tests/Services/Fakes/LoggerFake.cs

@@ -15,7 +15,7 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services.Fakes
 
         public IDisposable BeginScope<TState>(TState state)
         {
-            return null;
+            return null!;
         }
     }
 }

+ 18 - 2
Tests/qdr.app.qlbrc.base.Tests/Services/SettingsServiceTest.cs

@@ -4,9 +4,12 @@ using Quadarax.Application.QLiberace.Base.Repositories;
 using Quadarax.Application.QLiberace.Base.Services;
 using Quadarax.Application.QLiberace.Base.Tests.Services.Fakes;
 using Quadarax.Application.QLiberace.Common;
+using Quadarax.Application.QLiberace.Common.Domain;
 using Quadarax.Foundation.Core.Data;
 using Quadarax.Foundation.Core.Data.Domain;
+using Quadarax.Foundation.Core.Data.Interface.Domain;
 using Quadarax.Foundation.Core.Value.Extensions;
+#pragma warning disable CS8625
 
 namespace Quadarax.Application.QLiberace.Base.Tests.Services
 {
@@ -16,12 +19,12 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services
         
         protected override RepoSetting GetRepository()
         {
-            return new RepoSetting(Uow.As<IDataDomain>());
+            return new RepoSetting(Uow.As<IDataDomain>(), new QlbrcContext(null,"default", 1));
         }
 
         protected override SettingsService GetService()
         {
-            return new SettingsService(GetRepository(), null, new LoggerFactoryFake());
+            return new SettingsService(GetRepository(), new ContextFake(), new LoggerFactoryFake());
         }
 
 
@@ -475,5 +478,18 @@ namespace Quadarax.Application.QLiberace.Base.Tests.Services
             Assert.That(settingGot.Values.Count, Is.EqualTo(0));
         }
 
+
+        protected override void OnSetup()
+        {
+            base.OnSetup();
+            var repoTenant = new RepoTenant(Uow.As<IDataDomain>());
+            var tenant = repoTenant.New();
+            tenant.Code = "default";
+            tenant.Name = "Default system tenant";
+            tenant.IsLocked = false;
+            repoTenant.Set(tenant);
+            Uow.Commit();
+        }
+
     }
 }

+ 3 - 2
Tests/qdr.app.qlbrc.common.Tests/Repositories/CommonRepositoryTest.cs

@@ -1,4 +1,5 @@
 using qdr.fnd.core.test;
+using Quadarax.Application.QLiberace.Common.Domain;
 using Quadarax.Application.QLiberace.Common.Tests.Repositories.Fakes;
 using Quadarax.Foundation.Core.Data.Domain;
 
@@ -7,12 +8,12 @@ namespace Quadarax.Application.QLiberace.Common.Tests.Repositories
     [TestFixture(Category = "Dao")]
     public class CommonRepositoryTest : RepositoryDbContextTest<TestTenantTrackedRepo, TestDbContext>
     {
-        private const string Modifier = "testmod";
+        private const string Modifier = "genericIdentity";
 
         
         protected override TestTenantTrackedRepo GetRepository()
         {
-            return new TestTenantTrackedRepo(Uow.As<IDataDomain>(), Modifier);
+            return new TestTenantTrackedRepo(Uow.As<IDataDomain>(), new QlbrcContext(null,null, null));
         }
 
         [Test]

+ 1 - 1
Tests/qdr.app.qlbrc.common.Tests/Repositories/Fakes/TestTenantTrackedDao.cs

@@ -2,7 +2,7 @@
 
 namespace Quadarax.Application.QLiberace.Common.Tests.Repositories.Fakes
 {
-    public class TestTenantTrackedDao : QlbrcEntityTrackedWithId
+    public class TestTenantTrackedDao : QlbrcEntityTracked
     {
     }
 }

+ 3 - 2
Tests/qdr.app.qlbrc.common.Tests/Repositories/Fakes/TestTenantTrackedRepo.cs

@@ -1,4 +1,5 @@
-using Quadarax.Application.QLiberace.Common.Repositories;
+using Quadarax.Application.QLiberace.Common.Domain;
+using Quadarax.Application.QLiberace.Common.Repositories;
 using Quadarax.Foundation.Core.Data.Domain;
 using Quadarax.Foundation.Core.Data.Interface.Domain;
 
@@ -6,7 +7,7 @@ namespace Quadarax.Application.QLiberace.Common.Tests.Repositories.Fakes
 {
     public  class TestTenantTrackedRepo : QlbrcTrackedRepository<TestTenantTrackedDao>
     {
-        public TestTenantTrackedRepo(IUnitOfWork<IDataDomain> unitOfWork, string modifier) : base(unitOfWork, modifier)
+        public TestTenantTrackedRepo(IUnitOfWork<IDataDomain> unitOfWork, QlbrcContext operationContext) : base(unitOfWork, operationContext)
         {
         }
     }