Skip to content

Commit b8ac6a9

Browse files
Refactor order notification with new command and handler
1 parent 63aadfb commit b8ac6a9

File tree

3 files changed

+130
-102
lines changed

3 files changed

+130
-102
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
using Grand.Business.Core.Commands.Messages.Common;
2+
using Grand.Business.Core.Interfaces.Checkout.Orders;
3+
using Grand.Business.Core.Interfaces.Common.Pdf;
4+
using Grand.Business.Core.Interfaces.Messages;
5+
using Grand.Business.Core.Queries.Checkout.Orders;
6+
using Grand.Domain.Localization;
7+
using Grand.Domain.Orders;
8+
using MediatR;
9+
using Microsoft.Extensions.Logging;
10+
11+
namespace Grand.Business.Checkout.Commands.Handlers.Orders;
12+
13+
public class OrderNotificationCommandHandler : IRequestHandler<OrderNotificationCommand>
14+
{
15+
private readonly IOrderService _orderService;
16+
private readonly IMessageProviderService _messageProviderService;
17+
private readonly OrderSettings _orderSettings;
18+
private readonly LanguageSettings _languageSettings;
19+
private readonly IPdfService _pdfService;
20+
private readonly ILogger<OrderNotificationCommandHandler> _logger;
21+
private readonly IMediator _mediator;
22+
23+
public OrderNotificationCommandHandler(
24+
IOrderService orderService,
25+
IMessageProviderService messageProviderService,
26+
OrderSettings orderSettings,
27+
LanguageSettings languageSettings,
28+
IPdfService pdfService,
29+
ILogger<OrderNotificationCommandHandler> logger,
30+
IMediator mediator)
31+
{
32+
_orderService = orderService;
33+
_messageProviderService = messageProviderService;
34+
_orderSettings = orderSettings;
35+
_languageSettings = languageSettings;
36+
_pdfService = pdfService;
37+
_logger = logger;
38+
_mediator = mediator;
39+
}
40+
41+
public async Task Handle(OrderNotificationCommand request, CancellationToken cancellationToken)
42+
{
43+
44+
try
45+
{
46+
if (request.WorkContext.OriginalCustomerIfImpersonated != null)
47+
//this order is placed by a store administrator impersonating a customer
48+
await _orderService.InsertOrderNote(new OrderNote {
49+
Note =
50+
$"Order placed by a store owner ('{request.WorkContext.OriginalCustomerIfImpersonated.Email}'. ID = {request.WorkContext.OriginalCustomerIfImpersonated.Id}) impersonating the customer.",
51+
DisplayToCustomer = false,
52+
OrderId = request.Order.Id
53+
});
54+
else
55+
await _orderService.InsertOrderNote(new OrderNote {
56+
Note = "Order placed",
57+
DisplayToCustomer = false,
58+
OrderId = request.Order.Id
59+
});
60+
61+
//send email notifications
62+
await _messageProviderService.SendOrderPlacedStoreOwnerMessage(request.Order, request.WorkContext.CurrentCustomer,
63+
_languageSettings.DefaultAdminLanguageId);
64+
65+
string orderPlacedAttachmentFilePath = string.Empty, orderPlacedAttachmentFileName = string.Empty;
66+
var orderPlacedAttachments = new List<string>();
67+
68+
try
69+
{
70+
orderPlacedAttachmentFilePath =
71+
_orderSettings.AttachPdfInvoiceToOrderPlacedEmail && !_orderSettings.AttachPdfInvoiceToBinary
72+
? await _pdfService.PrintOrderToPdf(request.Order, request.Order.CustomerLanguageId)
73+
: null;
74+
orderPlacedAttachmentFileName =
75+
_orderSettings.AttachPdfInvoiceToOrderPlacedEmail && !_orderSettings.AttachPdfInvoiceToBinary
76+
? "order.pdf"
77+
: null;
78+
orderPlacedAttachments = _orderSettings.AttachPdfInvoiceToOrderPlacedEmail &&
79+
_orderSettings.AttachPdfInvoiceToBinary
80+
? [
81+
await _pdfService.SaveOrderToBinary(request.Order, request.Order.CustomerLanguageId)
82+
]
83+
: [];
84+
}
85+
catch (Exception ex)
86+
{
87+
_logger.LogError(ex, "Error - order placed attachment file {OrderOrderNumber}", request.Order.OrderNumber);
88+
}
89+
90+
await _messageProviderService.SendOrderPlacedCustomerMessage(request.Order, request.WorkContext.CurrentCustomer, request.Order.CustomerLanguageId, orderPlacedAttachmentFilePath, orderPlacedAttachmentFileName, orderPlacedAttachments);
91+
92+
if (request.Order.OrderItems.Any(x => !string.IsNullOrEmpty(x.VendorId)))
93+
{
94+
var vendors = await _mediator.Send(new GetVendorsInOrderQuery { Order = request.Order });
95+
foreach (var vendor in vendors)
96+
await _messageProviderService.SendOrderPlacedVendorMessage(request.Order, request.WorkContext.CurrentCustomer, vendor,
97+
_languageSettings.DefaultAdminLanguageId);
98+
}
99+
}
100+
catch (Exception e)
101+
{
102+
_logger.LogError(e, "Place order send notification error");
103+
}
104+
}
105+
}

src/Business/Grand.Business.Checkout/Commands/Handlers/Orders/PlaceOrderCommandHandler.cs

Lines changed: 13 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Grand.Business.Core.Commands.Checkout.Orders;
2+
using Grand.Business.Core.Commands.Messages.Common;
23
using Grand.Business.Core.Events.Checkout.Orders;
34
using Grand.Business.Core.Extensions;
45
using Grand.Business.Core.Interfaces.Catalog.Discounts;
@@ -11,7 +12,6 @@
1112
using Grand.Business.Core.Interfaces.Checkout.Payments;
1213
using Grand.Business.Core.Interfaces.Common.Directory;
1314
using Grand.Business.Core.Interfaces.Common.Localization;
14-
using Grand.Business.Core.Interfaces.Common.Pdf;
1515
using Grand.Business.Core.Interfaces.Customers;
1616
using Grand.Business.Core.Interfaces.Messages;
1717
using Grand.Business.Core.Queries.Checkout.Orders;
@@ -20,7 +20,6 @@
2020
using Grand.Domain.Common;
2121
using Grand.Domain.Customers;
2222
using Grand.Domain.Discounts;
23-
using Grand.Domain.Localization;
2423
using Grand.Domain.Orders;
2524
using Grand.Domain.Payments;
2625
using Grand.Domain.Shipping;
@@ -29,7 +28,6 @@
2928
using Grand.SharedKernel;
3029
using Grand.SharedKernel.Extensions;
3130
using MediatR;
32-
using Microsoft.Extensions.DependencyInjection;
3331
using Microsoft.Extensions.Logging;
3432

3533
namespace Grand.Business.Checkout.Commands.Handlers.Orders;
@@ -61,7 +59,6 @@ public class PlaceOrderCommandHandler : IRequestHandler<PlaceOrderCommand, Place
6159
private readonly IProductReservationService _productReservationService;
6260
private readonly IProductService _productService;
6361
private readonly ISalesEmployeeService _salesEmployeeService;
64-
private readonly IServiceScopeFactory _serviceScopeFactory;
6562
private readonly ShippingSettings _shippingSettings;
6663
private readonly ShoppingCartSettings _shoppingCartSettings;
6764
private readonly IShoppingCartValidator _shoppingCartValidator;
@@ -98,7 +95,6 @@ public PlaceOrderCommandHandler(
9895
IAuctionService auctionService,
9996
ICountryService countryService,
10097
IShoppingCartValidator shoppingCartValidator,
101-
IServiceScopeFactory serviceScopeFactory,
10298
ShippingSettings shippingSettings,
10399
ShoppingCartSettings shoppingCartSettings,
104100
PaymentSettings paymentSettings,
@@ -132,7 +128,6 @@ public PlaceOrderCommandHandler(
132128
_auctionService = auctionService;
133129
_countryService = countryService;
134130
_shoppingCartValidator = shoppingCartValidator;
135-
_serviceScopeFactory = serviceScopeFactory;
136131
_shippingSettings = shippingSettings;
137132
_shoppingCartSettings = shoppingCartSettings;
138133
_paymentSettings = paymentSettings;
@@ -182,9 +177,7 @@ await UpdatePaymentTransaction(processPayment.paymentTransaction, result.PlacedO
182177

183178
#region Events & notes
184179

185-
_ = Task.Run(
186-
() => SendNotification(_serviceScopeFactory, result.PlacedOrder, _workContextAccessor.WorkContext.CurrentCustomer,
187-
_workContextAccessor.WorkContext.OriginalCustomerIfImpersonated), cancellationToken);
180+
await _mediator.Send(new OrderNotificationCommand { Order = result.PlacedOrder, WorkContext = _workContextAccessor.WorkContext }, cancellationToken);
188181

189182
//check order status
190183
await _mediator.Send(new CheckOrderStatusCommand { Order = result.PlacedOrder }, cancellationToken);
@@ -359,19 +352,19 @@ private async Task<double> GetShoppingCartItemWeight(ShoppingCartItem shoppingCa
359352
switch (attributeValue.AttributeValueTypeId)
360353
{
361354
case AttributeValueType.Simple:
362-
{
363-
//simple attribute
364-
attributesTotalWeight += attributeValue.WeightAdjustment;
365-
}
355+
{
356+
//simple attribute
357+
attributesTotalWeight += attributeValue.WeightAdjustment;
358+
}
366359
break;
367360
case AttributeValueType.AssociatedToProduct:
368-
{
369-
//bundled product
370-
var associatedProduct =
371-
await _productService.GetProductById(attributeValue.AssociatedProductId);
372-
if (associatedProduct is { IsShipEnabled: true })
373-
attributesTotalWeight += associatedProduct.Weight * attributeValue.Quantity;
374-
}
361+
{
362+
//bundled product
363+
var associatedProduct =
364+
await _productService.GetProductById(attributeValue.AssociatedProductId);
365+
if (associatedProduct is { IsShipEnabled: true })
366+
attributesTotalWeight += associatedProduct.Weight * attributeValue.Quantity;
367+
}
375368
break;
376369
}
377370
}
@@ -1030,86 +1023,4 @@ protected virtual async Task<Order> SaveOrderDetails(PlaceOrderContainer details
10301023

10311024
return order;
10321025
}
1033-
1034-
/// <summary>
1035-
/// Send notification order
1036-
/// </summary>
1037-
/// <param name="scopeFactory"></param>
1038-
/// <param name="order">Order</param>
1039-
/// <param name="customer"></param>
1040-
/// <param name="originalCustomerIfImpersonated"></param>
1041-
protected virtual async Task SendNotification(IServiceScopeFactory scopeFactory, Order order, Customer customer,
1042-
Customer originalCustomerIfImpersonated)
1043-
{
1044-
using var scope = scopeFactory.CreateScope();
1045-
var orderService = scope.ServiceProvider.GetRequiredService<IOrderService>();
1046-
var messageProviderService = scope.ServiceProvider.GetRequiredService<IMessageProviderService>();
1047-
var orderSettings = scope.ServiceProvider.GetRequiredService<OrderSettings>();
1048-
var languageSettings = scope.ServiceProvider.GetRequiredService<LanguageSettings>();
1049-
var pdfService = scope.ServiceProvider.GetRequiredService<IPdfService>();
1050-
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
1051-
try
1052-
{
1053-
//notes, messages
1054-
if (originalCustomerIfImpersonated != null)
1055-
//this order is placed by a store administrator impersonating a customer
1056-
await orderService.InsertOrderNote(new OrderNote {
1057-
Note =
1058-
$"Order placed by a store owner ('{originalCustomerIfImpersonated.Email}'. ID = {originalCustomerIfImpersonated.Id}) impersonating the customer.",
1059-
DisplayToCustomer = false,
1060-
OrderId = order.Id
1061-
});
1062-
else
1063-
await orderService.InsertOrderNote(new OrderNote {
1064-
Note = "Order placed",
1065-
DisplayToCustomer = false,
1066-
OrderId = order.Id
1067-
});
1068-
1069-
//send email notifications
1070-
await messageProviderService.SendOrderPlacedStoreOwnerMessage(order, customer,
1071-
languageSettings.DefaultAdminLanguageId);
1072-
1073-
string orderPlacedAttachmentFilePath = string.Empty, orderPlacedAttachmentFileName = string.Empty;
1074-
var orderPlacedAttachments = new List<string>();
1075-
1076-
try
1077-
{
1078-
orderPlacedAttachmentFilePath =
1079-
orderSettings.AttachPdfInvoiceToOrderPlacedEmail && !orderSettings.AttachPdfInvoiceToBinary
1080-
? await pdfService.PrintOrderToPdf(order, order.CustomerLanguageId)
1081-
: null;
1082-
orderPlacedAttachmentFileName =
1083-
orderSettings.AttachPdfInvoiceToOrderPlacedEmail && !orderSettings.AttachPdfInvoiceToBinary
1084-
? "order.pdf"
1085-
: null;
1086-
orderPlacedAttachments = orderSettings.AttachPdfInvoiceToOrderPlacedEmail &&
1087-
orderSettings.AttachPdfInvoiceToBinary
1088-
? [
1089-
await pdfService.SaveOrderToBinary(order, order.CustomerLanguageId)
1090-
]
1091-
: [];
1092-
}
1093-
catch (Exception ex)
1094-
{
1095-
_logger.LogError(ex, "Error - order placed attachment file {OrderOrderNumber}", order.OrderNumber);
1096-
}
1097-
1098-
await messageProviderService
1099-
.SendOrderPlacedCustomerMessage(order, customer, order.CustomerLanguageId,
1100-
orderPlacedAttachmentFilePath, orderPlacedAttachmentFileName, orderPlacedAttachments);
1101-
1102-
if (order.OrderItems.Any(x => !string.IsNullOrEmpty(x.VendorId)))
1103-
{
1104-
var vendors = await mediator.Send(new GetVendorsInOrderQuery { Order = order });
1105-
foreach (var vendor in vendors)
1106-
await messageProviderService.SendOrderPlacedVendorMessage(order, customer, vendor,
1107-
languageSettings.DefaultAdminLanguageId);
1108-
}
1109-
}
1110-
catch (Exception e)
1111-
{
1112-
_logger.LogError(e, "Place order send notification error");
1113-
}
1114-
}
11151026
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using Grand.Domain.Customers;
2+
using Grand.Domain.Orders;
3+
using Grand.Infrastructure;
4+
using MediatR;
5+
6+
namespace Grand.Business.Core.Commands.Messages.Common;
7+
8+
public class OrderNotificationCommand : IRequest
9+
{
10+
public Order Order { get; set; }
11+
public IWorkContext WorkContext { get; set; }
12+
}

0 commit comments

Comments
 (0)