Browse Source

CustomerService (not completed)

Dalibor Votruba 3 years ago
parent
commit
5c41e65df3

+ 13 - 0
Common/qdr.app.qlbrc.common/ExceptionLibrary.cs

@@ -22,6 +22,10 @@ namespace Quadarax.Application.QLiberace.Common
 
             AddCode(ExceptionsCodes.UserNotFoundCode, ExceptionsCodes.UserNotFoundMsg);
             AddCode(ExceptionsCodes.UserAlreadyExistsCode, ExceptionsCodes.UserAlreadyExistsMsg);
+
+            AddCode(ExceptionsCodes.CustomerNotFoundCode, ExceptionsCodes.CustomerNotFoundMsg);
+            AddCode(ExceptionsCodes.CustomerUserAlreadyAssignedCode, ExceptionsCodes.CustomerUserAlreadyAssignedMsg);
+            AddCode(ExceptionsCodes.CustomerUserNotFoundAssignedCode, ExceptionsCodes.CustomerUserNotFoundAssignedMsg);
         }
 
 
@@ -52,6 +56,15 @@ namespace Quadarax.Application.QLiberace.Common
             public const int UserNotFoundCode = 10020;
             public const string UserAlreadyExistsMsg = "User with login name '{0}' already exists";
             public const int UserAlreadyExistsCode = 10021;
+
+
+            public const string CustomerNotFoundMsg = "Customer with identifier {0}='{1}' not found";
+            public const int CustomerNotFoundCode = 10030;
+            public const string CustomerUserAlreadyAssignedMsg = "Customer with identifier {0}='{1}' has already user '{2}' assigned.";
+            public const int CustomerUserAlreadyAssignedCode = 10031;
+            public const string CustomerUserNotFoundAssignedMsg = "Customer with identifier {0}='{1}' has no user '{2}' assigned.";
+            public const int CustomerUserNotFoundAssignedCode = 10032;
+
             
         }
 

+ 57 - 0
Common/qdr.fnd.core.test/Value/EnumExtTest.cs

@@ -0,0 +1,57 @@
+using NUnit.Framework.Internal;
+using Quadarax.Foundation.Core.Value.Extensions;
+
+namespace qdr.fnd.core.test.Value
+{
+    [TestFixture(Category = "Fnd.Core")]
+    public class EnumExtTest : BaseTest
+    {
+        private enum TestEnum
+        {
+            One,
+            Two,
+            Three
+        }
+        private enum TestEnum2
+        {
+            One2,
+            Two2,
+            Three2
+        }
+
+        protected override void OnSetup()
+        {
+        }
+
+        protected override void OnTearDown()
+        {
+        }
+
+
+        [Test]
+        public void InOK()
+        {
+            TestEnum value = TestEnum.Three;
+
+            Assert.That(value.In(TestEnum.One), Is.False);
+            Assert.That(value.In(TestEnum.One, TestEnum.Two), Is.False);
+            Assert.That(value.In(TestEnum.One, TestEnum.Two, TestEnum.Three), Is.True);
+            Assert.That(value.In(TestEnum.Three), Is.True);
+            Assert.That(value.In("Three"), Is.False);
+            Assert.That(value.In("TestEnum.Three"), Is.False);
+            Assert.That(value.In("XX"), Is.False);
+
+        }
+
+        [Test]
+        public void InFail()
+        {
+            TestEnum value = TestEnum.Three;
+
+            // empty tenant code
+            Assert.That(Assert.Throws<ArgumentNullException>(() =>
+                        value.In(null))?.ParamName,
+                Is.EqualTo("values"));
+        }
+    }
+}

+ 19 - 0
Common/qdr.fnd.core/Value/Extensions/EnumExt.cs

@@ -0,0 +1,19 @@
+using System;
+
+namespace Quadarax.Foundation.Core.Value.Extensions
+{
+    public static class EnumExt
+    {
+        public static bool In<TEnum>(this TEnum owner, params object[] values) where TEnum : Enum
+        {
+            if (values == null) throw new ArgumentNullException(nameof(values));
+
+            foreach (var value in values)
+            {
+                if (Equals(owner, value)) return true;
+            }
+
+            return false;
+        }
+    }
+}

+ 52 - 0
Modules/qdr.app.qlbrc.customer/Dtos/Validators/ContactValidator.cs

@@ -0,0 +1,52 @@
+using Quadarax.Application.QLiberace.Base.Repositories;
+using Quadarax.Application.QLiberace.Customer.Enums;
+using Quadarax.Foundation.Core.Value;
+using Quadarax.Foundation.Core.Value.Extensions;
+
+namespace Quadarax.Application.QLiberace.Customer.Dtos.Validators
+{
+    public class ContactValidator : Validator<ContactWDto>
+    {
+        protected override void OnValidate(ContactWDto validatingObject, ValidatorContext context)
+        {
+        
+        
+            CheckIfEmpty("Address", validatingObject.Address, ValidationResult.ValidationSeverityEnum.Error);
+            CheckIfStringMaxLengthOverflow("Address", validatingObject.Address, 100,
+                ValidationResult.ValidationSeverityEnum.Error);
+            
+            CheckIfStringMaxLengthOverflow("Address1", validatingObject.Address1, 100,
+                ValidationResult.ValidationSeverityEnum.Error);
+
+            CheckIfEmpty("Caption", validatingObject.Caption, ValidationResult.ValidationSeverityEnum.Error);
+            CheckIfStringMaxLengthOverflow("Caption", validatingObject.Caption, 100,
+                ValidationResult.ValidationSeverityEnum.Error);
+
+            if (validatingObject.Type == ContactTypeEnum.Address)
+            {
+                CheckIfEmpty("City", validatingObject.City, ValidationResult.ValidationSeverityEnum.Error);
+                CheckIfStringMaxLengthOverflow("City", validatingObject.City, 50,
+                    ValidationResult.ValidationSeverityEnum.Error);
+
+                CheckIfEmpty("Zip", validatingObject.Zip, ValidationResult.ValidationSeverityEnum.Error);
+                CheckIfStringMaxLengthOverflow("Zip", validatingObject.Zip, 20,
+                    ValidationResult.ValidationSeverityEnum.Error);
+
+            }
+            if (validatingObject.Type.In(ContactTypeEnum.Address, ContactTypeEnum.Phone, ContactTypeEnum.Sms))
+            {
+                CheckIfEmpty("CountryCode", validatingObject.CountryCode, ValidationResult.ValidationSeverityEnum.Error);
+                CheckIfStringMaxLengthOverflow("CountryCode", validatingObject.CountryCode, 100,
+                    ValidationResult.ValidationSeverityEnum.Error);
+                if (!string.IsNullOrEmpty(validatingObject.CountryCode))
+                {
+                    var rcurr = context.GetValue<RepoCountry>("RepoCountry");
+                    CheckIfNull("CountryCode", rcurr.GetByCode(validatingObject.CountryCode),
+                        ValidationResult.ValidationSeverityEnum.Error,
+                        $"Contact CountryCode not match country code '{validatingObject.CountryCode}' with enumeration");
+                }
+            }
+
+        }
+    }
+}

+ 33 - 0
Modules/qdr.app.qlbrc.customer/Dtos/Validators/CustomerValidator.cs

@@ -0,0 +1,33 @@
+using Quadarax.Application.QLiberace.Base.Repositories;
+using Quadarax.Foundation.Core.Value;
+
+namespace Quadarax.Application.QLiberace.Customer.Dtos.Validators
+{
+    public class CustomerValidator : Validator<CustomerWDto>
+    {
+
+        protected override void OnValidate(CustomerWDto validatingObject, ValidatorContext context)
+        {
+            CheckIfEmpty("Name", validatingObject.Name, ValidationResult.ValidationSeverityEnum.Error);
+            CheckIfStringMaxLengthOverflow("Name", validatingObject.Name, 100,
+                ValidationResult.ValidationSeverityEnum.Error);
+
+            CheckIfEmpty("TaxCountryCode", validatingObject.TaxCountryCode, ValidationResult.ValidationSeverityEnum.Error);
+            CheckIfStringMaxLengthOverflow("TaxCountryCode", validatingObject.TaxCountryCode, 5,
+                ValidationResult.ValidationSeverityEnum.Error);
+            if (!string.IsNullOrEmpty(validatingObject.TaxCountryCode))
+            {
+                var rcurr = context.GetValue<RepoCountry>("RepoCountry");
+                CheckIfNull("TaxCountryCode",rcurr.GetByCode(validatingObject.TaxCountryCode), ValidationResult.ValidationSeverityEnum.Error, $"Customer TaxCountryCode not match country code '{validatingObject.TaxCountryCode}' with enumeration");
+            }
+            
+            CheckIfStringMaxLengthOverflow("TaxNumber", validatingObject.TaxNumber, 20,
+                ValidationResult.ValidationSeverityEnum.Error);
+
+            CheckIfStringMaxLengthOverflow("VatNumber", validatingObject.VatNumber, 20,
+                ValidationResult.ValidationSeverityEnum.Error);
+
+        }
+    }
+
+}

+ 3 - 0
Modules/qdr.app.qlbrc.customer/Entities/Customer.cs

@@ -33,9 +33,12 @@ namespace Quadarax.Application.QLiberace.Customer.Entities
 
         public virtual ICollection<Contact> Contacts { get; set; } = null!;
 
+        public virtual ICollection<CustomerUser> Users { get; set; } = null!;
+
         public Customer()
         {
             Contacts = new List<Contact>();
+            Users = new List<CustomerUser>();
         }
 
     }

+ 3 - 0
Modules/qdr.app.qlbrc.customer/Entities/DaoMapper/CustomerDm.cs

@@ -45,6 +45,9 @@ namespace Quadarax.Application.QLiberace.Customer.Entities.DaoMapper
                         .HasMaxLength(20)
                         .HasComment("Customer VAT number (VAT identification)");
 
+
+
+
                 }
             );
         }

+ 6 - 6
Modules/qdr.app.qlbrc.customer/Entities/DaoMapper/CustomerUserDm.cs

@@ -29,14 +29,14 @@ namespace Quadarax.Application.QLiberace.Customer.Entities.DaoMapper
                         .HasMaxLength(100)
                         .HasComment("Reference to user");
 
+                    
                     // relationships
-                    entity.HasOne(d => d.Customer)
-                        .WithMany()
-                        .HasForeignKey(d => d.CustomerId)
+                    entity.HasOne(pc => pc.Customer)
+                        .WithMany(p => p.Users)
+                        .HasForeignKey(pc => pc.CustomerId)
                         .OnDelete(DeleteBehavior.NoAction)
-                        .HasConstraintName("REL_CUSTOMETUSER_CUSTOMER_ID");
-
-
+                        .HasConstraintName("REL_CUSTOMERUSER_CUSTOMER_ID");
+                    
                 }
             );
         }

+ 142 - 13
Modules/qdr.app.qlbrc.customer/Services/CustomerService.cs

@@ -1,18 +1,26 @@
 using Microsoft.Extensions.Logging;
+using Quadarax.Application.QLiberace.Base.Dtos;
+using Quadarax.Application.QLiberace.Base.Entities;
+using Quadarax.Application.QLiberace.Base.Mapper;
 using Quadarax.Application.QLiberace.Base.Repositories;
+using Quadarax.Application.QLiberace.Common;
+using Quadarax.Application.QLiberace.Common.Domain;
 using Quadarax.Application.QLiberace.Customer.Dtos;
+using Quadarax.Application.QLiberace.Customer.Dtos.Validators;
+using Quadarax.Application.QLiberace.Customer.Entities;
 using Quadarax.Application.QLiberace.Customer.Enums;
 using Quadarax.Application.QLiberace.Customer.Repositories;
 using Quadarax.Foundation.Core.Business;
 using Quadarax.Foundation.Core.Data.Interface.Domain;
 using Quadarax.Foundation.Core.Data.Interface.Entity.Dto;
+using Quadarax.Foundation.Core.Value;
 
 namespace Quadarax.Application.QLiberace.Customer.Services
 {
-    public class CustomerService : AbstractMultiRepositoryService<RepoCustomer,RepoContact, RepoUser>
+    public class CustomerService : AbstractMultiRepositoryService<RepoCustomer,RepoContact, RepoUser, RepoCountry>
     {
         #region *** Constructor ***
-        public CustomerService(RepoCustomer repository1, RepoContact repository2, RepoUser repository3, IContext currentContext, ILoggerFactory logger) : base(repository1, repository2, repository3, currentContext, logger)
+        public CustomerService(RepoCustomer repository1, RepoContact repository2, RepoUser repository3, RepoCountry repository4, IContext currentContext, ILoggerFactory logger) : base(repository1, repository2, repository3, repository4, currentContext, logger)
         {
         }
         #endregion
@@ -20,54 +28,121 @@ namespace Quadarax.Application.QLiberace.Customer.Services
         #region *** Public operations ***
         #region **** Customer ****
 
-        public ResultValueDto<CustomerRDto?> AddCustomer(CustomerWDto customer)
+        public ResultValueDto<CustomerRDto?> CreateCustomer(CustomerWDto customer)
         {
-            throw new NotImplementedException();
+            if (customer==null) throw new ArgumentNullException(nameof(customer));
+
+            return TryCatchBlock(() =>
+            {
+                ValidateWDto(customer);
+
+                var customerDao = Repository1.New();
+                customer.CopyToDto(customerDao);
+                return new ResultValueDto<CustomerRDto?>(customerDao.Map<Entities.Customer, CustomerRDto>());
+            });
         }
 
 
         public ResultDto UpdateCustomer(string customerCode, CustomerWDto customer)
         {
-            throw new NotImplementedException();
+            if (customer==null) throw new ArgumentNullException(nameof(customer));
+
+            return TryCatchBlock(() =>
+            {
+                ValidateWDto(customer);
+
+                var customerDao = FetchCustomer(customerCode);
+                customer.CopyToDto(customerDao);
+                return new ResultValueDto<CustomerRDto?>(customerDao.Map<Entities.Customer, CustomerRDto>());
+            });
         }
 
         public ResultDto DeleteCustomer(long customerId)
         {
-            throw new NotImplementedException();
+            return TryCatchBlock(() =>
+            {
+                var result = FetchCustomer(customerId);
+                Repository1.Remove(customerId);
+                return new ResultPlain();
+            });
         }
 
         public ResultValueDto<CustomerRDto?> GetCustomer(string customerCode)
         {
-            throw new NotImplementedException();
+            return TryCatchBlock(() =>
+            {
+                var customerDao = FetchCustomer(customerCode);
+                return new ResultValueDto<CustomerRDto?>(customerDao.Map<Entities.Customer, CustomerRDto>());
+            });
         }
 
         public ResultValueDto<CustomerRDto?> GetCustomer(long customerId)
         {
-            throw new NotImplementedException();
+            return TryCatchBlock(() =>
+            {
+                var customerDao = FetchCustomer(customerId);
+                return new ResultValueDto<CustomerRDto?>(customerDao.Map<Entities.Customer, CustomerRDto>());
+            });
         }
 
         public ResultBoolDto ExistsCustomer(string customerCode)
         {
-            throw new NotImplementedException();
+            return TryCatchBlock(() => new ResultBoolDto(FetchCustomer(customerCode)!=null));
         }
         #endregion
 
         #region **** User Assignments ****
         public ResultDto AssignUser(string customerCode, string userLogin)
         {
-            throw new NotImplementedException();
+            return TryCatchBlock(() =>
+            {
+                var customerDao = FetchCustomer(customerCode);
+                FetchUser(userLogin);
+                
+                if (customerDao!.Users.Any(x=>string.Equals(x.UserLoginName, userLogin)))
+                    throw ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.CustomerUserAlreadyAssignedCode, "code",customerCode, userLogin);
+
+                customerDao.Users.Add(new CustomerUser()
+                {
+                    CustomerId = customerDao.Id,
+                    UserLoginName = userLogin
+                });
+                return new ResultPlain();
+            });
         }
 
         public ResultDto UnAssignUser(string customerCode, string userLogin)
         {
-            throw new NotImplementedException();
+            return TryCatchBlock(() =>
+            {
+                var customerDao = FetchCustomer(customerCode);
+                FetchUser(userLogin);
+
+                var customerUser = customerDao!.Users.FirstOrDefault(x => string.Equals(x.UserLoginName, userLogin));
+                if (customerUser == null)
+                    throw ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.CustomerUserNotFoundAssignedCode, "code",customerCode, userLogin);
+
+                customerDao.Users.Remove(customerUser);
+                return new ResultPlain();
+            });
         }
         #endregion
 
         #region **** Customer Constacts ****
-        public ResultValueDto<ContactRDto?> AddContact(string customerCode, ContactWDto contact)
+        public ResultValueDto<ContactRDto?> CreateContact(string customerCode, ContactWDto contact)
         {
-            throw new NotImplementedException();
+
+            if (contact==null) throw new ArgumentNullException(nameof(contact));
+
+            return TryCatchBlock(() =>
+            {
+                var customerDao = FetchCustomer(customerCode);
+                ValidateWDto(contact);
+
+                var contactDao = Repository2.New();
+                contact.CopyToDto(contactDao);
+                return new ResultValueDto<ContactRDto?>(contactDao.Map<Contact, ContactRDto>());
+            });
         }
         public ResultDto UpdateContact(string customerCode, ContactWDto contact)
         {
@@ -101,6 +176,60 @@ namespace Quadarax.Application.QLiberace.Customer.Services
         #endregion
         #endregion
 
+        #region *** Private Operations ***
+        private void ValidateWDto(CustomerWDto customer)
+        {
+            if (customer == null) throw new ArgumentNullException(nameof(customer));
+            var validator = new CustomerValidator();
+            validator.Validate(customer, new ValidatorContext(new KeyValuePair<string, object>[]{ new("RepoCountry", Repository4)}));
+            if (!validator.IsSuccess) throw ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.ValidationErrorsCode, validator.ToAggregateException());
+        }
+
+        private void ValidateWDto(ContactWDto contact)
+        {
+            if (contact == null) throw new ArgumentNullException(nameof(contact));
+            var validator = new ContactValidator();
+            validator.Validate(contact, new ValidatorContext(new KeyValuePair<string, object>[]{ new("RepoCountry", Repository4)}));
+            if (!validator.IsSuccess) throw ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.ValidationErrorsCode, validator.ToAggregateException());
+        }
+
+        private void ValidateSameTenant(TenantWDto tenant)
+        {
+            if (tenant == null) throw new ArgumentNullException(nameof(tenant));
+            var currentTenantCode = CurrentContext.GetContext<QlbrcContext>().TenantCode;
+            if (!string.Equals(currentTenantCode, tenant.Code, StringComparison.InvariantCulture))
+                throw ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.TenantDifferentContextCode, tenant.Code, currentTenantCode!);
+        }
+
+        private Entities.Customer? FetchCustomer(string customerCode)
+        {
+            if (string.IsNullOrEmpty(customerCode)) throw new ArgumentNullException(nameof(customerCode));
+
+            var exists = Repository1.GetByCode(customerCode);
+            if (exists != null) throw 
+                ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.CustomerNotFoundCode, "code", customerCode);
+            return exists;
+        }
+
+        private User? FetchUser(string userLogin)
+        {
+            if (string.IsNullOrEmpty(userLogin)) throw new ArgumentNullException(nameof(userLogin));
+
+            var exists = Repository3.GetByLoginName(userLogin);
+            if (exists != null) throw 
+                ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.UserNotFoundCode, "loginName", userLogin);
+            return exists;
+        }
+
+        private Entities.Customer? FetchCustomer(long customerId)
+        {
+            var exists = Repository1.Get(customerId);
+            if (exists != null) throw 
+                ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.CustomerNotFoundCode, "id", customerId.ToString());
+            return exists;
+        }
+        #endregion
+
     }
 
 

+ 0 - 4
Modules/qdr.app.qlbrc.customer/qdr.app.qlbrc.customer.csproj

@@ -14,8 +14,4 @@
     <ProjectReference Include="..\qdr.app.qlbrc.base\qdr.app.qlbrc.base.csproj" />
   </ItemGroup>
 
-  <ItemGroup>
-    <Folder Include="Dtos\Validators\" />
-  </ItemGroup>
-
 </Project>