Skip to content

Commit

Permalink
Refactor order notification with new command and handler
Browse files Browse the repository at this point in the history
  • Loading branch information
KrzysztofPajak committed Dec 29, 2024
1 parent 63aadfb commit b8ac6a9
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 102 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using Grand.Business.Core.Commands.Messages.Common;
using Grand.Business.Core.Interfaces.Checkout.Orders;
using Grand.Business.Core.Interfaces.Common.Pdf;
using Grand.Business.Core.Interfaces.Messages;
using Grand.Business.Core.Queries.Checkout.Orders;
using Grand.Domain.Localization;
using Grand.Domain.Orders;
using MediatR;
using Microsoft.Extensions.Logging;

namespace Grand.Business.Checkout.Commands.Handlers.Orders;

public class OrderNotificationCommandHandler : IRequestHandler<OrderNotificationCommand>
{
private readonly IOrderService _orderService;
private readonly IMessageProviderService _messageProviderService;
private readonly OrderSettings _orderSettings;
private readonly LanguageSettings _languageSettings;
private readonly IPdfService _pdfService;
private readonly ILogger<OrderNotificationCommandHandler> _logger;
private readonly IMediator _mediator;

public OrderNotificationCommandHandler(
IOrderService orderService,
IMessageProviderService messageProviderService,
OrderSettings orderSettings,
LanguageSettings languageSettings,
IPdfService pdfService,
ILogger<OrderNotificationCommandHandler> logger,
IMediator mediator)
{
_orderService = orderService;
_messageProviderService = messageProviderService;
_orderSettings = orderSettings;
_languageSettings = languageSettings;
_pdfService = pdfService;
_logger = logger;
_mediator = mediator;
}

public async Task Handle(OrderNotificationCommand request, CancellationToken cancellationToken)
{

try
{
if (request.WorkContext.OriginalCustomerIfImpersonated != null)
//this order is placed by a store administrator impersonating a customer
await _orderService.InsertOrderNote(new OrderNote {
Note =
$"Order placed by a store owner ('{request.WorkContext.OriginalCustomerIfImpersonated.Email}'. ID = {request.WorkContext.OriginalCustomerIfImpersonated.Id}) impersonating the customer.",
DisplayToCustomer = false,
OrderId = request.Order.Id
});
else
await _orderService.InsertOrderNote(new OrderNote {
Note = "Order placed",
DisplayToCustomer = false,
OrderId = request.Order.Id
});

//send email notifications
await _messageProviderService.SendOrderPlacedStoreOwnerMessage(request.Order, request.WorkContext.CurrentCustomer,
_languageSettings.DefaultAdminLanguageId);

string orderPlacedAttachmentFilePath = string.Empty, orderPlacedAttachmentFileName = string.Empty;
var orderPlacedAttachments = new List<string>();

try
{
orderPlacedAttachmentFilePath =
_orderSettings.AttachPdfInvoiceToOrderPlacedEmail && !_orderSettings.AttachPdfInvoiceToBinary
? await _pdfService.PrintOrderToPdf(request.Order, request.Order.CustomerLanguageId)
: null;
orderPlacedAttachmentFileName =
_orderSettings.AttachPdfInvoiceToOrderPlacedEmail && !_orderSettings.AttachPdfInvoiceToBinary
? "order.pdf"
: null;
orderPlacedAttachments = _orderSettings.AttachPdfInvoiceToOrderPlacedEmail &&
_orderSettings.AttachPdfInvoiceToBinary
? [
await _pdfService.SaveOrderToBinary(request.Order, request.Order.CustomerLanguageId)
]
: [];
}
catch (Exception ex)
{
_logger.LogError(ex, "Error - order placed attachment file {OrderOrderNumber}", request.Order.OrderNumber);
}

await _messageProviderService.SendOrderPlacedCustomerMessage(request.Order, request.WorkContext.CurrentCustomer, request.Order.CustomerLanguageId, orderPlacedAttachmentFilePath, orderPlacedAttachmentFileName, orderPlacedAttachments);

if (request.Order.OrderItems.Any(x => !string.IsNullOrEmpty(x.VendorId)))
{
var vendors = await _mediator.Send(new GetVendorsInOrderQuery { Order = request.Order });
foreach (var vendor in vendors)
await _messageProviderService.SendOrderPlacedVendorMessage(request.Order, request.WorkContext.CurrentCustomer, vendor,
_languageSettings.DefaultAdminLanguageId);
}
}
catch (Exception e)
{
_logger.LogError(e, "Place order send notification error");
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Grand.Business.Core.Commands.Checkout.Orders;
using Grand.Business.Core.Commands.Messages.Common;
using Grand.Business.Core.Events.Checkout.Orders;
using Grand.Business.Core.Extensions;
using Grand.Business.Core.Interfaces.Catalog.Discounts;
Expand All @@ -11,7 +12,6 @@
using Grand.Business.Core.Interfaces.Checkout.Payments;
using Grand.Business.Core.Interfaces.Common.Directory;
using Grand.Business.Core.Interfaces.Common.Localization;
using Grand.Business.Core.Interfaces.Common.Pdf;
using Grand.Business.Core.Interfaces.Customers;
using Grand.Business.Core.Interfaces.Messages;
using Grand.Business.Core.Queries.Checkout.Orders;
Expand All @@ -20,7 +20,6 @@
using Grand.Domain.Common;
using Grand.Domain.Customers;
using Grand.Domain.Discounts;
using Grand.Domain.Localization;
using Grand.Domain.Orders;
using Grand.Domain.Payments;
using Grand.Domain.Shipping;
Expand All @@ -29,7 +28,6 @@
using Grand.SharedKernel;
using Grand.SharedKernel.Extensions;
using MediatR;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

namespace Grand.Business.Checkout.Commands.Handlers.Orders;
Expand Down Expand Up @@ -61,7 +59,6 @@ public class PlaceOrderCommandHandler : IRequestHandler<PlaceOrderCommand, Place
private readonly IProductReservationService _productReservationService;
private readonly IProductService _productService;
private readonly ISalesEmployeeService _salesEmployeeService;
private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly ShippingSettings _shippingSettings;
private readonly ShoppingCartSettings _shoppingCartSettings;
private readonly IShoppingCartValidator _shoppingCartValidator;
Expand Down Expand Up @@ -98,7 +95,6 @@ public PlaceOrderCommandHandler(
IAuctionService auctionService,
ICountryService countryService,
IShoppingCartValidator shoppingCartValidator,
IServiceScopeFactory serviceScopeFactory,
ShippingSettings shippingSettings,
ShoppingCartSettings shoppingCartSettings,
PaymentSettings paymentSettings,
Expand Down Expand Up @@ -132,7 +128,6 @@ public PlaceOrderCommandHandler(
_auctionService = auctionService;
_countryService = countryService;
_shoppingCartValidator = shoppingCartValidator;
_serviceScopeFactory = serviceScopeFactory;
_shippingSettings = shippingSettings;
_shoppingCartSettings = shoppingCartSettings;
_paymentSettings = paymentSettings;
Expand Down Expand Up @@ -182,9 +177,7 @@ await UpdatePaymentTransaction(processPayment.paymentTransaction, result.PlacedO

#region Events & notes

_ = Task.Run(
() => SendNotification(_serviceScopeFactory, result.PlacedOrder, _workContextAccessor.WorkContext.CurrentCustomer,
_workContextAccessor.WorkContext.OriginalCustomerIfImpersonated), cancellationToken);
await _mediator.Send(new OrderNotificationCommand { Order = result.PlacedOrder, WorkContext = _workContextAccessor.WorkContext }, cancellationToken);

//check order status
await _mediator.Send(new CheckOrderStatusCommand { Order = result.PlacedOrder }, cancellationToken);
Expand Down Expand Up @@ -359,19 +352,19 @@ private async Task<double> GetShoppingCartItemWeight(ShoppingCartItem shoppingCa
switch (attributeValue.AttributeValueTypeId)
{
case AttributeValueType.Simple:
{
//simple attribute
attributesTotalWeight += attributeValue.WeightAdjustment;
}
{
//simple attribute
attributesTotalWeight += attributeValue.WeightAdjustment;
}
break;
case AttributeValueType.AssociatedToProduct:
{
//bundled product
var associatedProduct =
await _productService.GetProductById(attributeValue.AssociatedProductId);
if (associatedProduct is { IsShipEnabled: true })
attributesTotalWeight += associatedProduct.Weight * attributeValue.Quantity;
}
{
//bundled product
var associatedProduct =
await _productService.GetProductById(attributeValue.AssociatedProductId);
if (associatedProduct is { IsShipEnabled: true })
attributesTotalWeight += associatedProduct.Weight * attributeValue.Quantity;
}
break;
}
}
Expand Down Expand Up @@ -1030,86 +1023,4 @@ protected virtual async Task<Order> SaveOrderDetails(PlaceOrderContainer details

return order;
}

/// <summary>
/// Send notification order
/// </summary>
/// <param name="scopeFactory"></param>
/// <param name="order">Order</param>
/// <param name="customer"></param>
/// <param name="originalCustomerIfImpersonated"></param>
protected virtual async Task SendNotification(IServiceScopeFactory scopeFactory, Order order, Customer customer,
Customer originalCustomerIfImpersonated)
{
using var scope = scopeFactory.CreateScope();
var orderService = scope.ServiceProvider.GetRequiredService<IOrderService>();
var messageProviderService = scope.ServiceProvider.GetRequiredService<IMessageProviderService>();
var orderSettings = scope.ServiceProvider.GetRequiredService<OrderSettings>();
var languageSettings = scope.ServiceProvider.GetRequiredService<LanguageSettings>();
var pdfService = scope.ServiceProvider.GetRequiredService<IPdfService>();
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
try
{
//notes, messages
if (originalCustomerIfImpersonated != null)
//this order is placed by a store administrator impersonating a customer
await orderService.InsertOrderNote(new OrderNote {
Note =
$"Order placed by a store owner ('{originalCustomerIfImpersonated.Email}'. ID = {originalCustomerIfImpersonated.Id}) impersonating the customer.",
DisplayToCustomer = false,
OrderId = order.Id
});
else
await orderService.InsertOrderNote(new OrderNote {
Note = "Order placed",
DisplayToCustomer = false,
OrderId = order.Id
});

//send email notifications
await messageProviderService.SendOrderPlacedStoreOwnerMessage(order, customer,
languageSettings.DefaultAdminLanguageId);

string orderPlacedAttachmentFilePath = string.Empty, orderPlacedAttachmentFileName = string.Empty;
var orderPlacedAttachments = new List<string>();

try
{
orderPlacedAttachmentFilePath =
orderSettings.AttachPdfInvoiceToOrderPlacedEmail && !orderSettings.AttachPdfInvoiceToBinary
? await pdfService.PrintOrderToPdf(order, order.CustomerLanguageId)
: null;
orderPlacedAttachmentFileName =
orderSettings.AttachPdfInvoiceToOrderPlacedEmail && !orderSettings.AttachPdfInvoiceToBinary
? "order.pdf"
: null;
orderPlacedAttachments = orderSettings.AttachPdfInvoiceToOrderPlacedEmail &&
orderSettings.AttachPdfInvoiceToBinary
? [
await pdfService.SaveOrderToBinary(order, order.CustomerLanguageId)
]
: [];
}
catch (Exception ex)
{
_logger.LogError(ex, "Error - order placed attachment file {OrderOrderNumber}", order.OrderNumber);
}

await messageProviderService
.SendOrderPlacedCustomerMessage(order, customer, order.CustomerLanguageId,
orderPlacedAttachmentFilePath, orderPlacedAttachmentFileName, orderPlacedAttachments);

if (order.OrderItems.Any(x => !string.IsNullOrEmpty(x.VendorId)))
{
var vendors = await mediator.Send(new GetVendorsInOrderQuery { Order = order });
foreach (var vendor in vendors)
await messageProviderService.SendOrderPlacedVendorMessage(order, customer, vendor,
languageSettings.DefaultAdminLanguageId);
}
}
catch (Exception e)
{
_logger.LogError(e, "Place order send notification error");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Grand.Domain.Customers;
using Grand.Domain.Orders;
using Grand.Infrastructure;
using MediatR;

namespace Grand.Business.Core.Commands.Messages.Common;

public class OrderNotificationCommand : IRequest
{
public Order Order { get; set; }
public IWorkContext WorkContext { get; set; }
}

0 comments on commit b8ac6a9

Please sign in to comment.