Try your search with a different keyword or use * as a wildcard.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.Routing;
using Nop.Core;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Customers;
using Nop.Core.Domain.Directory;
using Nop.Core.Domain.Orders;
using Nop.Core.Domain.Tax;
using Nop.Plugin.Misc.Brevo.MarketingAutomation;
using Nop.Services.Catalog;
using Nop.Services.Common;
using Nop.Services.Customers;
using Nop.Services.Directory;
using Nop.Services.Logging;
using Nop.Services.Media;
using Nop.Services.Orders;
using Nop.Services.Seo;
using Nop.Web.Framework.Mvc.Routing;
namespace Nop.Plugin.Misc.Brevo.Services;
///
/// Represents Brevo marketing automation manager
///
public class MarketingAutomationManager
{
#region Fields
protected readonly BrevoSettings _brevoSettings;
protected readonly CurrencySettings _currencySettings;
protected readonly IActionContextAccessor _actionContextAccessor;
protected readonly IAddressService _addressService;
protected readonly ICategoryService _categoryService;
protected readonly ICountryService _countryService;
protected readonly ICurrencyService _currencyService;
protected readonly ICustomerService _customerService;
protected readonly IGenericAttributeService _genericAttributeService;
protected readonly ILogger _logger;
protected readonly INopUrlHelper _nopUrlHelper;
protected readonly IOrderService _orderService;
protected readonly IOrderTotalCalculationService _orderTotalCalculationService;
protected readonly IPictureService _pictureService;
protected readonly IProductAttributeParser _productAttributeParser;
protected readonly IProductService _productService;
protected readonly IShoppingCartService _shoppingCartService;
protected readonly IStateProvinceService _stateProvinceService;
protected readonly IStoreContext _storeContext;
protected readonly IUrlHelperFactory _urlHelperFactory;
protected readonly IUrlRecordService _urlRecordService;
protected readonly IWebHelper _webHelper;
protected readonly IWorkContext _workContext;
protected readonly MarketingAutomationHttpClient _marketingAutomationHttpClient;
#endregion
#region Ctor
public MarketingAutomationManager(BrevoSettings brevoSettings,
CurrencySettings currencySettings,
IActionContextAccessor actionContextAccessor,
IAddressService addressService,
ICategoryService categoryService,
ICountryService countryService,
ICurrencyService currencyService,
ICustomerService customerService,
IGenericAttributeService genericAttributeService,
ILogger logger,
INopUrlHelper nopUrlHelper,
IOrderService orderService,
IOrderTotalCalculationService orderTotalCalculationService,
IPictureService pictureService,
IProductAttributeParser productAttributeParser,
IProductService productService,
IShoppingCartService shoppingCartService,
IStateProvinceService stateProvinceService,
IStoreContext storeContext,
IUrlHelperFactory urlHelperFactory,
IUrlRecordService urlRecordService,
IWebHelper webHelper,
IWorkContext workContext,
MarketingAutomationHttpClient marketingAutomationHttpClient)
{
_brevoSettings = brevoSettings;
_currencySettings = currencySettings;
_actionContextAccessor = actionContextAccessor;
_addressService = addressService;
_categoryService = categoryService;
_countryService = countryService;
_currencyService = currencyService;
_customerService = customerService;
_genericAttributeService = genericAttributeService;
_logger = logger;
_nopUrlHelper = nopUrlHelper;
_orderService = orderService;
_orderTotalCalculationService = orderTotalCalculationService;
_pictureService = pictureService;
_productAttributeParser = productAttributeParser;
_productService = productService;
_shoppingCartService = shoppingCartService;
_stateProvinceService = stateProvinceService;
_storeContext = storeContext;
_urlHelperFactory = urlHelperFactory;
_urlRecordService = urlRecordService;
_webHelper = webHelper;
_workContext = workContext;
_marketingAutomationHttpClient = marketingAutomationHttpClient;
}
#endregion
#region Methods
///
/// Handle shopping cart changed event
///
/// Shopping cart item
/// A task that represents the asynchronous operation
public async Task HandleShoppingCartChangedEventAsync(ShoppingCartItem cartItem)
{
//whether marketing automation is enabled
if (!_brevoSettings.UseMarketingAutomation)
return;
var customer = await _customerService.GetCustomerByIdAsync(cartItem.CustomerId);
try
{
//first, try to identify current customer
await _marketingAutomationHttpClient.RequestAsync(new IdentifyRequest { Email = customer.Email });
//get shopping cart GUID
var shoppingCartGuid = await _genericAttributeService
.GetAttributeAsync(customer, BrevoDefaults.ShoppingCartGuidAttribute);
//create track event object
var trackEvent = new TrackEventRequest { Email = customer.Email };
//get current customer's shopping cart
var store = await _storeContext.GetCurrentStoreAsync();
var cart = await _shoppingCartService
.GetShoppingCartAsync(customer, ShoppingCartType.ShoppingCart, store.Id);
if (cart.Any())
{
//get URL helper
var urlHelper = _urlHelperFactory.GetUrlHelper(_actionContextAccessor.ActionContext);
//get shopping cart amounts
var (cartDiscount, _, cartSubtotal, _, _) = await _orderTotalCalculationService.GetShoppingCartSubTotalAsync(cart,
await _workContext.GetTaxDisplayTypeAsync() == TaxDisplayType.IncludingTax);
var cartTax = await _orderTotalCalculationService.GetTaxTotalAsync(cart, false);
var cartShipping = await _orderTotalCalculationService.GetShoppingCartShippingTotalAsync(cart);
var (cartTotal, _, _, _, _, _) = await _orderTotalCalculationService.GetShoppingCartTotalAsync(cart, false, false);
//get products data by shopping cart items
var itemsData = await cart.Where(item => item.ProductId != 0).SelectAwait(async item =>
{
var product = await _productService.GetProductByIdAsync(item.ProductId);
//try to get product attribute combination
var combination = await _productAttributeParser.FindProductAttributeCombinationAsync(product, item.AttributesXml);
//get default product picture
var picture = await _pictureService.GetProductPictureAsync(product, item.AttributesXml);
//get product SEO slug name
var seName = await _urlRecordService.GetSeNameAsync(product);
//create product data
return new
{
id = product.Id,
name = product.Name,
variant_id = combination?.Id ?? product.Id,
variant_name = combination?.Sku ?? product.Name,
sku = combination?.Sku ?? product.Sku,
category = await (await _categoryService.GetProductCategoriesByProductIdAsync(item.ProductId)).AggregateAwaitAsync(",", async (all, pc) =>
{
var res = (await _categoryService.GetCategoryByIdAsync(pc.CategoryId)).Name;
res = all == "," ? res : all + ", " + res;
return res;
}),
url = await _nopUrlHelper.RouteGenericUrlAsync(new { SeName = seName }, _webHelper.GetCurrentRequestProtocol()),
image = (await _pictureService.GetPictureUrlAsync(picture)).Url,
quantity = item.Quantity,
price = (await _shoppingCartService.GetSubTotalAsync(item, true)).subTotal
};
}).ToArrayAsync();
//prepare cart data
var cartData = new
{
affiliation = store.Name,
subtotal = cartSubtotal,
shipping = cartShipping ?? decimal.Zero,
total_before_tax = cartSubtotal + cartShipping ?? decimal.Zero,
tax = cartTax,
discount = cartDiscount,
revenue = cartTotal ?? decimal.Zero,
url = urlHelper.RouteUrl("ShoppingCart", null, _webHelper.GetCurrentRequestProtocol()),
currency = (await _currencyService.GetCurrencyByIdAsync(_currencySettings.PrimaryStoreCurrencyId))?.CurrencyCode,
//gift_wrapping = string.Empty, //currently we can't get this value
items = itemsData
};
//if there is a single item in the cart, so the cart is just created
if (cart.Count == 1)
{
shoppingCartGuid = Guid.NewGuid();
}
else
{
//otherwise cart is updated
shoppingCartGuid ??= Guid.NewGuid();
}
trackEvent.EventName = BrevoDefaults.CartUpdatedEventName;
trackEvent.EventData = new { id = $"cart:{shoppingCartGuid}", data = cartData };
}
else
{
//there are no items in the cart, so the cart is deleted
shoppingCartGuid ??= Guid.NewGuid();
trackEvent.EventName = BrevoDefaults.CartDeletedEventName;
trackEvent.EventData = new { id = $"cart:{shoppingCartGuid}" };
}
//track event
await _marketingAutomationHttpClient.RequestAsync(trackEvent);
//update GUID for the current customer's shopping cart
await _genericAttributeService.SaveAttributeAsync(customer, BrevoDefaults.ShoppingCartGuidAttribute, shoppingCartGuid);
}
catch (Exception exception)
{
//log full error
await _logger.ErrorAsync($"Brevo Marketing Automation error: {exception.Message}.", exception, customer);
}
}
///
/// Handle order completed event
///
/// Order
/// A task that represents the asynchronous operation
public async Task HandleOrderCompletedEventAsync(Order order)
{
//whether marketing automation is enabled
if (!_brevoSettings.UseMarketingAutomation)
return;
ArgumentNullException.ThrowIfNull(order);
var customer = await _customerService.GetCustomerByIdAsync(order.CustomerId);
try
{
//first, try to identify current customer
await _marketingAutomationHttpClient.RequestAsync(new IdentifyRequest { Email = customer.Email });
//get URL helper
var urlHelper = _urlHelperFactory.GetUrlHelper(_actionContextAccessor.ActionContext);
//get products data by order items
var itemsData = await (await _orderService.GetOrderItemsAsync(order.Id)).SelectAwait(async item =>
{
var product = await _productService.GetProductByIdAsync(item.ProductId);
//try to get product attribute combination
var combination = await _productAttributeParser.FindProductAttributeCombinationAsync(product, item.AttributesXml);
//get default product picture
var picture = await _pictureService.GetProductPictureAsync(product, item.AttributesXml);
//get product SEO slug name
var seName = await _urlRecordService.GetSeNameAsync(product);
//create product data
return new
{
id = product.Id,
name = product.Name,
variant_id = combination?.Id ?? product.Id,
variant_name = combination?.Sku ?? product.Name,
sku = combination?.Sku ?? product.Sku,
category = await (await _categoryService.GetProductCategoriesByProductIdAsync(item.ProductId)).AggregateAwaitAsync(",", async (all, pc) =>
{
var res = (await _categoryService.GetCategoryByIdAsync(pc.CategoryId)).Name;
res = all == "," ? res : all + ", " + res;
return res;
}),
url = await _nopUrlHelper.RouteGenericUrlAsync(new { SeName = seName }, _webHelper.GetCurrentRequestProtocol()),
image = (await _pictureService.GetPictureUrlAsync(picture)).Url,
quantity = item.Quantity,
price = item.PriceInclTax,
};
}).ToArrayAsync();
var shippingAddress = await _addressService.GetAddressByIdAsync(order.ShippingAddressId ?? 0);
var billingAddress = await _addressService.GetAddressByIdAsync(order.BillingAddressId);
var shippingAddressData = new
{
firstname = shippingAddress?.FirstName,
lastname = shippingAddress?.LastName,
company = shippingAddress?.Company,
phone = shippingAddress?.PhoneNumber,
address1 = shippingAddress?.Address1,
address2 = shippingAddress?.Address2,
city = shippingAddress?.City,
country = (await _countryService.GetCountryByAddressAsync(shippingAddress))?.Name,
state = (await _stateProvinceService.GetStateProvinceByAddressAsync(shippingAddress))?.Name,
zipcode = shippingAddress?.ZipPostalCode
};
var billingAddressData = new
{
firstname = billingAddress?.FirstName,
lastname = billingAddress?.LastName,
company = billingAddress?.Company,
phone = billingAddress?.PhoneNumber,
address1 = billingAddress?.Address1,
address2 = billingAddress?.Address2,
city = billingAddress?.City,
country = (await _countryService.GetCountryByAddressAsync(billingAddress))?.Name,
state = (await _stateProvinceService.GetStateProvinceByAddressAsync(billingAddress))?.Name,
zipcode = billingAddress?.ZipPostalCode
};
var store = await _storeContext.GetCurrentStoreAsync();
//prepare cart data
var cartData = new
{
id = order.Id,
affiliation = customer.AffiliateId > 0 ? customer.AffiliateId.ToString() : store.Name,
date = order.PaidDateUtc?.ToString("yyyy-MM-dd"),
subtotal = order.OrderSubtotalInclTax,
shipping = order.OrderShippingInclTax,
total_before_tax = order.OrderSubtotalInclTax + order.OrderShippingInclTax,
tax = order.OrderTax,
discount = order.OrderDiscount,
revenue = order.OrderTotal,
url = urlHelper.RouteUrl("OrderDetails", new { orderId = order.Id }, _webHelper.GetCurrentRequestProtocol()),
currency = order.CustomerCurrencyCode,
//gift_wrapping = string.Empty, //currently we can't get this value
items = itemsData,
shipping_address = shippingAddressData,
billing_address = billingAddressData
};
//get shopping cart GUID
var shoppingCartGuid = await _genericAttributeService.GetAttributeAsync(order,
BrevoDefaults.ShoppingCartGuidAttribute) ?? Guid.NewGuid();
//create track event object
var trackEvent = new TrackEventRequest
{
Email = customer.Email,
EventName = BrevoDefaults.OrderCompletedEventName,
EventData = new { id = $"cart:{shoppingCartGuid}", data = cartData }
};
//track event
await _marketingAutomationHttpClient.RequestAsync(trackEvent);
//update GUID for the current customer's shopping cart
await _genericAttributeService.SaveAttributeAsync(order, BrevoDefaults.ShoppingCartGuidAttribute, null);
}
catch (Exception exception)
{
//log full error
await _logger.ErrorAsync($"Brevo Marketing Automation error: {exception.Message}.", exception, customer);
}
}
///
/// Handle order placed event
///
/// Order
/// A task that represents the asynchronous operation
public async Task HandleOrderPlacedEventAsync(Order order)
{
//whether marketing automation is enabled
if (!_brevoSettings.UseMarketingAutomation)
return;
//copy shopping cart GUID to order
var shoppingCartGuid = await _genericAttributeService.GetAttributeAsync(order.CustomerId, BrevoDefaults.ShoppingCartGuidAttribute);
await _genericAttributeService.SaveAttributeAsync(order, BrevoDefaults.ShoppingCartGuidAttribute, shoppingCartGuid);
}
#endregion
}