public async Task <PurchaseOrderResponse> Handle(PurchaseOrderRequest request, CancellationToken cancellationToken) { if (!await balanceValidationService.HasEnoughFunds(httpContextReader.CurrentUserId, request.TotalAmount)) { throw new PaymentException("Insufficient funds to complete transaction"); } var order = await orderService.PurchaseOrder(request); var orderOfferItems = order.Items.Where(i => i.Type == OrderType.Offer); var offersData = orderOfferItems.Select(i => new { OwnerId = i.OptionalData, Amount = (decimal)i.Amount / Constants.MoneyMultiplier }); foreach (var item in orderOfferItems) { var notification = await notifier.Push(NotificationMessages.OfferBoughtMessage(order.User.UserName, item.ProductName), item.OptionalData); await hubManager.Invoke(SignalrActions.NOTIFICATION_RECEIVED, item.OptionalData, mapper.Map <NotificationDto>(notification)); } var premiumOrder = order.Items.FirstOrDefault(i => i.Type == OrderType.Premium); if (premiumOrder != null && !await rolesManager.AdmitRole(RoleName.Premium, order.User)) { throw new PaymentException("Upgrading account to premium status failed"); } if (order != null) { foreach (var offerData in offersData) { await balanceService.AddBalance(offerData.OwnerId, offerData.Amount); await balanceService.AddBalance(order.UserId, -offerData.Amount); } string token = default(string); if (premiumOrder != null) { await balanceService.AddBalance(order.UserId, -(decimal)premiumOrder.Amount / Constants.MoneyMultiplier); token = await jwtAuthorizationTokenGenerator.GenerateToken(order.User); } return(new PurchaseOrderResponse { Order = mapper.Map <OrderDto>(order), Token = token }); } throw new PaymentException("Purchasing order failed"); }