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.Exceptions; using Quadarax.Foundation.Core.Logging; using Quadarax.Foundation.Core.Value; namespace Quadarax.Application.QLiberace.Customer.Services { public class CustomerService : AbstractMultiRepositoryService { #region *** Constructor *** public CustomerService(RepoCustomer repository1, RepoContact repository2, RepoUser repository3, RepoCountry repository4, IContext currentContext, IQLogger logger) : base(repository1, repository2, repository3, repository4, currentContext, logger) { } #endregion #region *** Public operations *** #region **** Customer **** public ResultValueDto CreateCustomer(CustomerWDto customer) { if (customer==null) throw new ArgumentNullException(nameof(customer)); return TryCatchBlock(() => { ValidateWDto(customer); var customerDao = Repository1.New(); customer.CopyToDto(customerDao); return new ResultValueDto(customerDao.Map()); }); } public ResultDto UpdateCustomer(string customerCode, CustomerWDto customer) { if (customer==null) throw new ArgumentNullException(nameof(customer)); return TryCatchBlock(() => { ValidateWDto(customer); var customerDao = FetchCustomer(customerCode); customer.CopyToDto(customerDao); return new ResultValueDto(customerDao.Map()); }); } public ResultDto DeleteCustomer(long customerId) { return TryCatchBlock(() => { var result = FetchCustomer(customerId); Repository1.Remove(customerId); return new ResultPlain(); }); } public ResultValueDto GetCustomer(string customerCode) { return TryCatchBlock(() => { var customerDao = FetchCustomer(customerCode); return new ResultValueDto(customerDao.Map()); }); } public ResultValueDto GetCustomer(long customerId) { return TryCatchBlock(() => { var customerDao = FetchCustomer(customerId); return new ResultValueDto(customerDao.Map()); }); } public ResultBoolDto ExistsCustomer(string customerCode) { return TryCatchBlock(() => new ResultBoolDto(FetchCustomer(customerCode)!=null)); } #endregion #region **** User Assignments **** public ResultDto AssignUser(string customerCode, string userLogin) { 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) { 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 CreateContact(string customerCode, ContactWDto contact) { if (contact==null) throw new ArgumentNullException(nameof(contact)); return TryCatchBlock(() => { var customerDao = FetchCustomer(customerCode); ValidateWDto(contact); var contactDao = Repository2.New(); contactDao.Customer = customerDao!; contact.CopyToDto(contactDao); return new ResultValueDto(contactDao.Map()); }); } public ResultDto UpdateContact(long contactId, ContactWDto contact) { if (contact==null) throw new ArgumentNullException(nameof(contact)); return TryCatchBlock(() => { var contactDao = FetchContact(contactId); ValidateWDto(contact); contact.CopyToDto(contactDao); return new ResultValueDto(contactDao.Map()); }); } public ResultDto DeleteContact(long contactId) { return TryCatchBlock(() => { Repository2.Remove(contactId); return new ResultPlain(); }); } public ResultValueDto GetContact(long contactId) { return TryCatchBlock(() => { var contactDao = FetchContact(contactId); return new ResultValueDto(contactDao.Map()); }); } public ResultsValueDto GetContacts(string customerCode) { return TryCatchBlock(() => { var customerDao = FetchCustomer(customerCode); return new ResultsValueDto(customerDao!.Contacts.MapList()); }); } public ResultsValueDto GetPreferredContacts(string customerCode, params ContactTypeEnum[] contactTypes) { if (contactTypes == null || contactTypes.Length == 0) throw new ArgumentNullException(nameof(contactTypes)); return TryCatchBlock(() => { var customerDao = FetchCustomer(customerCode); return new ResultsValueDto(customerDao!.Contacts.Where(x=>x.IsPreferred && contactTypes.Contains(x.Type)).MapList()); }); } public ResultDto ValidateContacts(string customerCode) { return TryCatchBlock(() => { var customerDao = FetchCustomer(customerCode); var contactTypes = new List(new[] { ContactTypeEnum.Address, ContactTypeEnum.Email, ContactTypeEnum.Phone }); var contacts = customerDao!.Contacts.Where(x => x.IsPreferred && contactTypes.Contains(x.Type)).ToArray(); if (contacts!=null && !contacts.Any()) throw ExceptionFactory.CreateException( ExceptionLibrary.ExceptionsCodes.CustomerMissingContactCode, "code", customerCode); var elist = new List(); if (contacts?.Count(x=>x.IsPreferred && x.Type == ContactTypeEnum.Address) != 1) elist.Add(ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.CustomerMissingAddressCode, "code",customerCode)); if (contacts?.Count(x=>x.IsPreferred && x.Type == ContactTypeEnum.Phone) != 1) elist.Add(ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.CustomerMissingPhoneCode, "code",customerCode)); if (contacts?.Count(x=>x.IsPreferred && x.Type == ContactTypeEnum.Email) != 1) elist.Add(ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.CustomerMissingEmailCode, "code",customerCode)); if (elist.Count > 0) throw new AggregateException(elist); return new ResultPlain(); }); } #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[]{ 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[]{ 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().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; } private Contact? FetchContact(long contactId) { var exists = Repository2.Get(contactId); if (exists != null) throw ExceptionFactory.CreateException(ExceptionLibrary.ExceptionsCodes.ContactNotFoundCode, "id", contactId.ToString()); return exists; } #endregion } }