using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Primitives; using Nop.Core; using Nop.Core.Domain.Customers; using Nop.Core.Domain.Gdpr; using Nop.Core.Domain.Orders; using Nop.Core.Events; using Nop.Core.Http.Extensions; using Nop.Services.Attributes; using Nop.Services.Catalog; using Nop.Services.Common; using Nop.Services.Customers; using Nop.Services.Events; using Nop.Services.Localization; using Nop.Services.Security; using Nop.Services.Tax; using Nop.Web.Areas.Admin.Models.Catalog; using Nop.Web.Areas.Admin.Models.Customers; using Nop.Web.Areas.Admin.Models.Orders; using Nop.Web.Framework.Events; using Nop.Web.Framework.Models; using Nop.Web.Models.Customer; namespace Nop.Plugin.Tax.Avalara.Services; /// /// Represents plugin event consumer /// public class EventConsumer : IConsumer, IConsumer, IConsumer>, IConsumer>, IConsumer>, IConsumer, IConsumer, IConsumer, IConsumer { #region Fields protected readonly AvalaraTaxManager _avalaraTaxManager; protected readonly AvalaraTaxSettings _avalaraTaxSettings; protected readonly IAttributeService _checkoutAttributeService; protected readonly ICustomerService _customerService; protected readonly IGenericAttributeService _genericAttributeService; protected readonly IHttpContextAccessor _httpContextAccessor; protected readonly ILocalizationService _localizationService; protected readonly IPermissionService _permissionService; protected readonly IProductService _productService; protected readonly ITaxPluginManager _taxPluginManager; protected readonly IWorkContext _workContext; #endregion #region Ctor public EventConsumer(AvalaraTaxManager avalaraTaxManager, AvalaraTaxSettings avalaraTaxSettings, IAttributeService checkoutAttributeService, ICustomerService customerService, IGenericAttributeService genericAttributeService, IHttpContextAccessor httpContextAccessor, ILocalizationService localizationService, IPermissionService permissionService, IProductService productService, ITaxPluginManager taxPluginManager, IWorkContext workContext) { _avalaraTaxManager = avalaraTaxManager; _avalaraTaxSettings = avalaraTaxSettings; _checkoutAttributeService = checkoutAttributeService; _customerService = customerService; _genericAttributeService = genericAttributeService; _httpContextAccessor = httpContextAccessor; _localizationService = localizationService; _permissionService = permissionService; _productService = productService; _taxPluginManager = taxPluginManager; _workContext = workContext; } #endregion #region Methods /// /// Handle customer activated event /// /// Event message /// A task that represents the asynchronous operation public async Task HandleEventAsync(CustomerActivatedEvent eventMessage) { if (eventMessage.Customer is null) return; //ensure that Avalara tax provider is active for the passed customer, since it's the event from the public area if (!await _taxPluginManager.IsPluginActiveAsync(AvalaraTaxDefaults.SystemName, eventMessage.Customer)) return; if (!_avalaraTaxSettings.EnableCertificates) return; //create customer await _avalaraTaxManager.CreateOrUpdateCustomerAsync(eventMessage.Customer); } /// /// Handle customer permanently deleted event /// /// Event message /// A task that represents the asynchronous operation public async Task HandleEventAsync(CustomerPermanentlyDeleted eventMessage) { //ensure that Avalara tax provider is active if (!await _taxPluginManager.IsPluginActiveAsync(AvalaraTaxDefaults.SystemName)) return; if (!_avalaraTaxSettings.EnableCertificates) return; //delete customer await _avalaraTaxManager.DeleteCustomerAsync(eventMessage.CustomerId); } /// /// Handle model prepared event /// /// Event message /// A task that represents the asynchronous operation public async Task HandleEventAsync(ModelPreparedEvent eventMessage) { var customerModel = eventMessage.Model as CustomerInfoModel; var navigationModel = eventMessage.Model as CustomerNavigationModel; if (customerModel is null && navigationModel is null) return; //ensure that Avalara tax provider is active for the passed customer, since it's the event from the public area var customer = await _workContext.GetCurrentCustomerAsync(); if (!await _taxPluginManager.IsPluginActiveAsync(AvalaraTaxDefaults.SystemName, customer)) return; if (!_avalaraTaxSettings.EnableCertificates) return; if (navigationModel is not null) { //ACL if (_avalaraTaxSettings.CustomerRoleIds.Any()) { var customerRoleIds = await _customerService.GetCustomerRoleIdsAsync(customer); if (!customerRoleIds.Intersect(_avalaraTaxSettings.CustomerRoleIds).Any()) return; } var infoItem = navigationModel.CustomerNavigationItems.FirstOrDefault(item => item.Tab == (int)CustomerNavigationEnum.Info); var position = navigationModel.CustomerNavigationItems.IndexOf(infoItem) + 1; navigationModel.CustomerNavigationItems.Insert(position, new CustomerNavigationItemModel { RouteName = AvalaraTaxDefaults.ExemptionCertificatesRouteName, ItemClass = AvalaraTaxDefaults.ExemptionCertificatesMenuClassName, Tab = AvalaraTaxDefaults.ExemptionCertificatesMenuTab, Title = await _localizationService.GetResourceAsync("Plugins.Tax.Avalara.ExemptionCertificates") }); } if (customerModel is not null && !_avalaraTaxSettings.AllowEditCustomer) await _avalaraTaxManager.CreateOrUpdateCustomerAsync(customer); } /// /// Handle model received event /// /// Event message /// A task that represents the asynchronous operation public async Task HandleEventAsync(ModelReceivedEvent eventMessage) { //get entity by received model var entity = eventMessage.Model switch { CustomerModel customerModel => (BaseEntity)await _customerService.GetCustomerByIdAsync(customerModel.Id), CustomerRoleModel customerRoleModel => await _customerService.GetCustomerRoleByIdAsync(customerRoleModel.Id), ProductModel productModel => await _productService.GetProductByIdAsync(productModel.Id), CheckoutAttributeModel checkoutAttributeModel => await _checkoutAttributeService.GetAttributeByIdAsync(checkoutAttributeModel.Id), _ => null }; if (entity == null) return; //ensure that Avalara tax provider is active if (!await _taxPluginManager.IsPluginActiveAsync(AvalaraTaxDefaults.SystemName)) return; if (!await _permissionService.AuthorizeAsync(StandardPermission.Configuration.MANAGE_TAX_SETTINGS)) return; //whether there is a form value for the entity use code var (keyExists, entityUseCodeValue) = await _httpContextAccessor.HttpContext.Request.TryGetFormValueAsync(AvalaraTaxDefaults.EntityUseCodeAttribute); if (keyExists && !StringValues.IsNullOrEmpty(entityUseCodeValue)) { //save attribute var entityUseCode = !entityUseCodeValue.ToString().Equals(Guid.Empty.ToString()) ? entityUseCodeValue.ToString() : null; await _genericAttributeService.SaveAttributeAsync(entity, AvalaraTaxDefaults.EntityUseCodeAttribute, entityUseCode); } } /// /// Handle order placed event /// /// Event message /// A task that represents the asynchronous operation public async Task HandleEventAsync(OrderPlacedEvent eventMessage) { if (eventMessage.Order == null) return; //ensure that Avalara tax provider is active for the passed customer, since it's the event from the public area var customer = await _customerService.GetCustomerByIdAsync(eventMessage.Order.CustomerId); if (!await _taxPluginManager.IsPluginActiveAsync(AvalaraTaxDefaults.SystemName, customer)) return; //create tax transaction await _avalaraTaxManager.CreateOrderTaxTransactionAsync(eventMessage.Order); } /// /// Handle order refunded event /// /// Event message /// A task that represents the asynchronous operation public async Task HandleEventAsync(OrderRefundedEvent eventMessage) { if (eventMessage.Order == null) return; //ensure that Avalara tax provider is active if (!await _taxPluginManager.IsPluginActiveAsync(AvalaraTaxDefaults.SystemName)) return; //refund tax transaction await _avalaraTaxManager.RefundTaxTransactionAsync(eventMessage.Order, eventMessage.Amount); } /// /// Handle order voided event /// /// Event message /// A task that represents the asynchronous operation public async Task HandleEventAsync(OrderVoidedEvent eventMessage) { if (eventMessage.Order == null) return; //ensure that Avalara tax provider is active if (!await _taxPluginManager.IsPluginActiveAsync(AvalaraTaxDefaults.SystemName)) return; //void tax transaction await _avalaraTaxManager.VoidTaxTransactionAsync(eventMessage.Order); } /// /// Handle order cancelled event /// /// Event message /// A task that represents the asynchronous operation public async Task HandleEventAsync(OrderStatusChangedEvent eventMessage) { if (eventMessage.Order == null) return; if (eventMessage.Order.OrderStatus != OrderStatus.Cancelled) return; //ensure that Avalara tax provider is active if (!await _taxPluginManager.IsPluginActiveAsync(AvalaraTaxDefaults.SystemName)) return; //void tax transaction await _avalaraTaxManager.VoidTaxTransactionAsync(eventMessage.Order); } /// /// Handle order deleted event /// /// Event message /// A task that represents the asynchronous operation public async Task HandleEventAsync(EntityDeletedEvent eventMessage) { if (eventMessage.Entity == null) return; //ensure that Avalara tax provider is active if (!await _taxPluginManager.IsPluginActiveAsync(AvalaraTaxDefaults.SystemName)) return; //delete tax transaction await _avalaraTaxManager.DeleteTaxTransactionAsync(eventMessage.Entity); } #endregion }