public void when_order_completed_then_order_dto_populated() { var orderCompleted = new OrderStatusChanged { SourceId = _orderId, Fare = 23, Toll = 2, Tip = 5, Tax = 12, Surcharge = 1, IsCompleted = true }; Sut.Handle(orderCompleted); using (var context = new BookingDbContext(DbName)) { var dto = context.Find <OrderDetail>(_orderId); Assert.NotNull(dto); Assert.NotNull(dto.Status == (int)OrderStatus.Completed); Assert.AreEqual(orderCompleted.Fare, dto.Fare); Assert.AreEqual(orderCompleted.Toll, dto.Toll); Assert.AreEqual(orderCompleted.Tip, dto.Tip); Assert.AreEqual(orderCompleted.Tax, dto.Tax); Assert.AreEqual(orderCompleted.Surcharge, dto.Surcharge); } }
public void when_amount_spent_attained_then_promotion_unlocked() { var accountId = Guid.NewGuid(); var orderId1 = Guid.NewGuid(); var orderId2 = Guid.NewGuid(); var newOrderStatus = new OrderStatusChanged { IsCompleted = true, Status = new OrderStatusDetail { AccountId = accountId, Status = OrderStatus.Completed } }; var newPaymentInit = new CreditCardPaymentInitiated { Meter = (decimal)15.31 }; var newPayment = new CreditCardPaymentCaptured_V2 { FeeType = FeeTypes.None, Meter = (decimal)15.31, AuthorizationCode = Guid.NewGuid().ToString(), AccountId = accountId }; _orderCreatedCommand.AccountId = accountId; _orderCreatedCommand.SourceId = orderId1; newOrderStatus.SourceId = orderId1; newPaymentInit.SourceId = orderId1; newPaymentInit.OrderId = orderId1; newPayment.SourceId = orderId1; newPayment.OrderId = orderId1; OrderGenerator.Handle(_orderCreatedCommand); OrderGenerator.Handle(newOrderStatus); CreditCardGenerator.Handle(newPaymentInit); CreditCardGenerator.Handle(newPayment); TriggerSut.Handle(newPayment); _orderCreatedCommand.SourceId = orderId2; newOrderStatus.SourceId = orderId2; newPaymentInit.SourceId = orderId2; newPaymentInit.OrderId = orderId2; newPayment.SourceId = orderId2; newPayment.OrderId = orderId2; OrderGenerator.Handle(_orderCreatedCommand); OrderGenerator.Handle(newOrderStatus); CreditCardGenerator.Handle(newPaymentInit); CreditCardGenerator.Handle(newPayment); TriggerSut.Handle(newPayment); var commands = Commands.OfType <AddUserToPromotionWhiteList>().Where(c => c.AccountIds.Contains(accountId)).ToArray(); Assert.AreEqual(1, commands.Count()); Assert.AreEqual(30.62, commands[0].LastTriggeredAmount); }
public void Handle(OrderStatusChanged @event) { using (var context = _contextFactory.Invoke()) { var orderReport = context.Find <OrderReportDetail>(@event.SourceId); orderReport.Payment.MdtFare = @event.Fare; orderReport.Payment.MdtTip = @event.Tip; orderReport.Payment.MdtToll = @event.Toll; if (@event.Status != null) { orderReport.Account.AccountId = @event.Status.AccountId; orderReport.VehicleInfos.DriverId = @event.Status.DriverInfos.DriverId; orderReport.VehicleInfos.DriverFirstName = @event.Status.DriverInfos.FirstName; orderReport.VehicleInfos.DriverLastName = @event.Status.DriverInfos.LastName; orderReport.VehicleInfos.Number = @event.Status.VehicleNumber; orderReport.VehicleInfos.Color = @event.Status.DriverInfos.VehicleColor; orderReport.VehicleInfos.Make = @event.Status.DriverInfos.VehicleMake; orderReport.VehicleInfos.Model = @event.Status.DriverInfos.VehicleModel; orderReport.VehicleInfos.Registration = @event.Status.DriverInfos.VehicleRegistration; orderReport.VehicleInfos.Type = @event.Status.DriverInfos.VehicleType; orderReport.OrderStatus.Status = @event.Status.Status; orderReport.OrderStatus.OrderIsNoShow = @event.Status.IBSStatusId == VehicleStatuses.Common.NoShow; orderReport.Order.PickupDateTime = @event.Status.PickupDate != DateTime.MinValue ? (DateTime?)@event.Status.PickupDate : null; orderReport.Order.CompanyName = @event.Status.CompanyName; } orderReport.OrderStatus.OrderIsCompleted = @event.IsCompleted; context.Save(orderReport); } }
public void when_ride_count_attained_then_promotion_unlocked() { var accountId = Guid.NewGuid(); var orderId1 = Guid.NewGuid(); var orderId2 = Guid.NewGuid(); var newOrderStatus = new OrderStatusChanged { IsCompleted = true, Status = new OrderStatusDetail { AccountId = accountId, Status = OrderStatus.Completed } }; _orderCreatedCommand.AccountId = accountId; _orderCreatedCommand.SourceId = orderId1; newOrderStatus.SourceId = orderId1; OrderGenerator.Handle(_orderCreatedCommand); OrderGenerator.Handle(newOrderStatus); TriggerSut.Handle(newOrderStatus); _orderCreatedCommand.SourceId = orderId2; newOrderStatus.SourceId = orderId2; OrderGenerator.Handle(_orderCreatedCommand); OrderGenerator.Handle(newOrderStatus); TriggerSut.Handle(newOrderStatus); var commands = Commands.OfType <AddUserToPromotionWhiteList>().Where(c => c.AccountIds.Contains(accountId)).ToArray(); Assert.AreEqual(1, commands.Count()); Assert.AreEqual(2, commands[0].LastTriggeredAmount); }
/// <summary> /// Event invocator for the OrderFilled event /// </summary> /// <param name="e">The OrderEvent</param> protected virtual void OnOrderEvent(OrderEvent e) { try { OrderStatusChanged?.Invoke(this, e); } catch (Exception err) { Log.Error(err); } }
public void Handle(OrderStatusChanged @event) { if (@event.IsCompleted) { var order = _orderDao.FindById(@event.SourceId); var orderStatus = _orderDao.FindOrderStatusById(@event.SourceId); var pairingInfo = _orderDao.FindOrderPairingById(@event.SourceId); var account = _accountDao.FindById(order.AccountId); if (_serverSettings.GetPaymentSettings(order.CompanyKey).PaymentMode == PaymentMethod.RideLinqCmt) { // Check if card declined InitializeCmtServiceClient(); if (CmtErrorCodes.IsTerminalError(orderStatus.PairingError)) { // Terminal error, no need to react to paymentFailure. return; } var trip = _cmtTripInfoServiceHelper.CheckForTripEndErrors(pairingInfo.PairingToken); if (trip != null && trip.ErrorCode == CmtErrorCodes.CardDeclined) { _commandBus.Send(new ReactToPaymentFailure { AccountId = order.AccountId, OrderId = order.Id, IBSOrderId = order.IBSOrderId, CreditCardId = account.DefaultCreditCard.GetValueOrDefault(), TransactionId = orderStatus.OrderId.ToString().Split('-').FirstOrDefault(), // Use first part of GUID to display to user OverdueAmount = Convert.ToDecimal(@event.Fare + @event.Tax + @event.Tip + @event.Toll), TransactionDate = @event.EventDate }); return; } // Since RideLinqCmt payment is processed automatically by CMT, we have to charge booking fees separately _feeService.ChargeBookingFeesIfNecessary(orderStatus); } // If the user has decided not to pair (paying the ride in car instead), // we have to void the amount that was preauthorized if (_serverSettings.GetPaymentSettings(order.CompanyKey).PaymentMode != PaymentMethod.RideLinqCmt && (order.Settings.ChargeTypeId == ChargeTypes.CardOnFile.Id || order.Settings.ChargeTypeId == ChargeTypes.PayPal.Id) && (pairingInfo == null || pairingInfo.WasUnpaired) && !orderStatus.IsPrepaid) //prepaid order will never have a pairing info { // void the preauthorization to prevent misuse fees _paymentService.VoidPreAuthorization(order.CompanyKey, @event.SourceId); } } }
/// <summary> /// Event invocator for the OrderFilled event /// </summary> /// <param name="e">The OrderEvent</param> protected virtual void OnOrderEvent(OrderEvent e) { try { Log.Debug("Brokerage.OnOrderEvent(): " + e); OrderStatusChanged?.Invoke(this, e); } catch (Exception err) { Log.Error(err); } }
/// <summary> /// Event invocator for the OrderFilled event /// </summary> /// <param name="e">The OrderEvent</param> protected virtual void OnOrderEvent(OrderEvent e) { try { OrderStatusChanged?.Invoke(this, e); if (Log.DebuggingEnabled) { // log after calling the OrderStatusChanged event, the BrokerageTransactionHandler will set the order quantity Log.Debug("Brokerage.OnOrderEvent(): " + e); } } catch (Exception err) { Log.Error(err); } }
private void OnOrderStatusChanged(OrderStatusChanged @event) { // special case for migration if (@event.IsCompleted) { _status = OrderStatus.Completed; } if (@event.Status != null) //possible with migration { _ibsStatus = @event.Status.IBSStatusId; _status = @event.Status.Status; } if (@event.Fare.HasValue && @event.Fare.Value > 0) { _fare = @event.Fare; } }
public void When(OrderStatusChanged @event) { this.SuppressEvent(); switch (@event.CurrentStatus) { case OrderStatus.Processing: this.Process(); break; case OrderStatus.Deliver: this.Deliver(); break; case OrderStatus.Closed: this.Closed(); break; case OrderStatus.Cancel: this.Cancel(); break; } this.UnsuppressedEvent(); }
private async Task CancelFailedPaymentOrders(CancellationToken stoppingToken) { var shouldCancelFailedPaymentOrders = _orderRepository.Query().Where(x => x.OrderStatus == OrderStatus.PendingPayment && x.UpdatedOn < DateTimeOffset.Now.AddMinutes(-5)); foreach (var order in shouldCancelFailedPaymentOrders) { order.OrderStatus = OrderStatus.Canceled; order.UpdatedOn = DateTimeOffset.Now; // TODO Rollback product stock var orderStatusChanged = new OrderStatusChanged { OrderId = order.Id, OldStatus = OrderStatus.PendingPayment, NewStatus = OrderStatus.Canceled, UserId = 0, Note = "System cancel" }; await _mediator.Publish(orderStatusChanged, stoppingToken); } await _orderRepository.SaveChangesAsync(); }
public async Task <IActionResult> ChangeStatus(long id, [FromBody] OrderStatusForm model) { var order = _orderRepository.Query().FirstOrDefault(x => x.Id == id); if (order == null) { return(NotFound()); } var currentUser = await _workContext.GetCurrentUser(); if (!User.IsInRole("admin") && order.VendorId != currentUser.VendorId) { return(BadRequest(new { error = "You don't have permission to manage this order" })); } if (Enum.IsDefined(typeof(OrderStatus), model.StatusId)) { order.OrderStatus = (OrderStatus)model.StatusId; await _orderRepository.SaveChangesAsync(); var orderStatusChanged = new OrderStatusChanged { OrderId = order.Id, OldStatus = OrderStatus.PendingPayment, NewStatus = OrderStatus.Canceled, UserId = 0, Note = "System cancel" }; await _mediator.Publish(orderStatusChanged); return(Accepted()); } return(BadRequest(new { Error = "unsupported order status" })); }
public void UpdateOrderStatus(OrderStatus orderStatus) { OrderStatusChanged?.Invoke(this, orderStatus); }
public void Do(DateTime?after = null) { var skip = 0; var hasMore = true; const int pageSize = 100000; after = after ?? DateTime.MinValue; Console.WriteLine("Migrating event since {0}", after); while (hasMore) { using (var context = _contextFactory.Invoke()) { context.Database.CommandTimeout = 0; // order by date then by version in case two events happened at the same time var events = context.Set <Event>() .OrderBy(x => x.EventDate) .ThenBy(x => x.Version) .Where(x => x.EventDate > after) .Skip(skip) .Take(pageSize) .ToList(); hasMore = events.Count == pageSize; Console.WriteLine("Number of events migrated: " + (hasMore ? skip : (skip + events.Count))); skip += pageSize; foreach (var message in events.Where(x => x.EventType == typeof(PaymentSettingUpdated).FullName).ToList()) { // fix BraintreeClientSettings namespace problem message.Payload = message.Payload.Replace("apcurium.MK.Common.Configuration.BraintreeClientSettings", "apcurium.MK.Common.Configuration.Impl.BraintreeClientSettings"); // fix PaymentSettingsUpdated events containing old PayPalCredentials message.Payload = message.Payload.Replace("apcurium.MK.Common.Configuration.Impl.PayPalCredentials", "apcurium.MK.Common.Configuration.Impl.PayPalServerCredentials"); } context.SaveChanges(); // rename Order Pairing events foreach (var message in events.Where(x => x.EventType.Contains("OrderPairedForRideLinqCmtPayment") || x.EventType.Contains("OrderUnpairedForRideLinqCmtPayment"))) { message.Payload = message.Payload.Replace("OrderPairedForRideLinqCmtPayment", "OrderPairedForPayment"); message.Payload = message.Payload.Replace("OrderUnpairedForRideLinqCmtPayment", "OrderUnpairedForPayment"); message.EventType = message.EventType.Replace("OrderPairedForRideLinqCmtPayment", "OrderPairedForPayment"); message.EventType = message.EventType.Replace("OrderUnpairedForRideLinqCmtPayment", "OrderUnpairedForPayment"); } context.SaveChanges(); // rename OrderCancelledBecauseOfIbsError events foreach (var message in events.Where(x => x.EventType.Equals("apcurium.MK.Booking.Events.OrderCancelledBecauseOfIbsError"))) { message.Payload = message.Payload.Replace("OrderCancelledBecauseOfIbsError", "OrderCancelledBecauseOfError"); message.EventType = message.EventType.Replace("OrderCancelledBecauseOfIbsError", "OrderCancelledBecauseOfError"); } context.SaveChanges(); // rename CreditCardAdded or CreditCardUpdated to CreditCardAddedOrUpdated foreach (var message in events.Where(x => x.EventType.Equals("apcurium.MK.Booking.Events.CreditCardAdded") || x.EventType.Equals("apcurium.MK.Booking.Events.CreditCardUpdated"))) { message.Payload = message.Payload.Replace("CreditCardAdded", "CreditCardAddedOrUpdated"); message.Payload = message.Payload.Replace("CreditCardUpdated", "CreditCardAddedOrUpdated"); message.EventType = message.EventType.Replace("CreditCardAdded", "CreditCardAddedOrUpdated"); message.EventType = message.EventType.Replace("CreditCardUpdated", "CreditCardAddedOrUpdated"); } context.SaveChanges(); // convert OrderCompleted to OrderStatusChanged foreach (var message in events.Where(x => x.EventType.Contains("OrderCompleted")).ToList()) { var @event = Deserialize <OrderCompleted>(message.Payload); var newEvent = new OrderStatusChanged { EventDate = @event.EventDate, SourceId = @event.SourceId, Version = @event.Version, Fare = @event.Fare, Tax = @event.Tax, Tip = @event.Tip, Toll = @event.Toll, IsCompleted = true }; message.Payload = Serialize(newEvent); message.EventType = message.EventType.Replace("OrderCompleted", "OrderStatusChanged"); } context.SaveChanges(); // convert CreditCardPaymentCaptured to CreditCardPaymentCaptured_V2 foreach (var message in events.Where(x => x.EventType.Equals("apcurium.MK.Booking.Events.CreditCardPaymentCaptured"))) { var @event = Deserialize <CreditCardPaymentCaptured>(message.Payload); var newEvent = Convert(@event); message.Payload = Serialize(newEvent); message.EventType = message.EventType.Replace("CreditCardPaymentCaptured", "CreditCardPaymentCaptured_V2"); } context.SaveChanges(); // convert UserAddedToPromotionWhiteList to UserAddedToPromotionWhiteList_V2 foreach (var message in events.Where(x => x.EventType.Equals("apcurium.MK.Booking.Events.UserAddedToPromotionWhiteList"))) { var @event = Deserialize <UserAddedToPromotionWhiteList>(message.Payload); var newEvent = Convert(@event); message.Payload = Serialize(newEvent); message.EventType = message.EventType.Replace("UserAddedToPromotionWhiteList", "UserAddedToPromotionWhiteList_V2"); } context.SaveChanges(); // convert OrderFareUpdated to OrderStatusChanged foreach (var message in events.Where(x => x.EventType.Contains("OrderFareUpdated")).ToList()) { var @event = Deserialize <OrderFareUpdated>(message.Payload); var newEvent = new OrderStatusChanged { EventDate = @event.EventDate, SourceId = @event.SourceId, Version = @event.Version, Fare = @event.Fare, Tax = @event.Tax, Tip = @event.Tip, Toll = @event.Toll, IsCompleted = false }; message.Payload = Serialize(newEvent); message.EventType = message.EventType.Replace("OrderFareUpdated", "OrderStatusChanged"); } context.SaveChanges(); // update OrderStatusChanged containing a Status with an invalid pickup date foreach (var message in events.Where(x => x.EventType.Equals("apcurium.MK.Booking.Events.OrderStatusChanged") && !x.Payload.Contains("\"Status\":null")) .ToList()) { var @event = Deserialize <OrderStatusChanged>(message.Payload); @event.Status.PickupDate = @event.Status.PickupDate < ((DateTime)SqlDateTime.MinValue) ? (DateTime)SqlDateTime.MinValue : @event.Status.PickupDate; message.Payload = Serialize(@event); } context.SaveChanges(); // update AppSettings foreach (var message in events.Where(x => x.EventType.Equals("apcurium.MK.Booking.Events.AppSettingsAddedOrUpdated"))) { message.Payload = message.Payload.Replace("\"Client.", "\""); message.Payload = message.Payload.Replace("\"DistanceFormat\": \"KM\"", "\"DistanceFormat\": \"Km\""); message.Payload = message.Payload.Replace("\"DistanceFormat\":\"KM\"", "\"DistanceFormat\":\"Km\""); message.Payload = message.Payload.Replace("\"AvailableVehiclesMarket\"", "\"HoneyBadger.AvailableVehiclesMarket\""); message.Payload = message.Payload.Replace("\"AvailableVehiclesFleetId\"", "\"HoneyBadger.AvailableVehiclesFleetId\""); } context.SaveChanges(); } } }
public void Handle(OrderStatusChanged @event) { using (var context = _contextFactory.Invoke()) { var fareAvailable = GetFareAvailable(@event.Fare); var details = context.Find <OrderStatusDetail>(@event.SourceId); if (details == null) { @event.Status.NetworkPairingTimeout = GetNetworkPairingTimeoutIfNecessary(@event.Status, @event.EventDate); @event.Status.ChargeAmountsTimeOut = GetChargeAmountsTimeoutIfNecessary(@event.Status, @event.EventDate); @event.Status.FareAvailable = fareAvailable; context.Set <OrderStatusDetail>().Add(@event.Status); } else { if (@event.Status != null) { details.NetworkPairingTimeout = GetNetworkPairingTimeoutIfNecessary(@event.Status, @event.EventDate); details.ChargeAmountsTimeOut = GetChargeAmountsTimeoutIfNecessary(@event.Status, @event.EventDate); details.IBSStatusId = @event.Status.IBSStatusId; details.DriverInfos = @event.Status.DriverInfos; details.VehicleNumber = @event.Status.VehicleNumber; details.TerminalId = @event.Status.TerminalId; details.ReferenceNumber = @event.Status.ReferenceNumber; details.Eta = @event.Status.Eta; details.Status = @event.Status.Status; details.IBSStatusDescription = @event.Status.IBSStatusDescription; details.PairingTimeOut = @event.Status.PairingTimeOut; details.PairingError = @event.Status.PairingError; details.RideLinqPairingCode = @event.Status.RideLinqPairingCode; details.TaxiAssignedDate = @event.Status.TaxiAssignedDate; } else { // it will enter here only with migration from OrderCompleted or OrderFareUpdated if (@event.IsCompleted) { details.Status = OrderStatus.Completed; } } details.FareAvailable = fareAvailable; context.Save(details); } var order = context.Find <OrderDetail>(@event.SourceId); if (order != null) { // possible only with migration from OrderCompleted or OrderFareUpdated if (@event.Status == null) { if (@event.IsCompleted) { order.Status = (int)OrderStatus.Completed; } } else { order.Status = (int)@event.Status.Status; } if (@event.IsCompleted) { RemoveTemporaryPaymentInfo(context, @event.SourceId); order.DropOffDate = @event.EventDate; } order.Fare = @event.Fare; order.Tip = @event.Tip; order.Toll = @event.Toll; order.Tax = @event.Tax; order.Surcharge = @event.Surcharge; context.Save(order); } else { _logger.LogMessage("Order Status without existing Order : " + @event.SourceId); } context.SaveChanges(); } }
public void Handle(OrderStatusChanged @event) { if (@event.IsCompleted) { if (@event.Status.IsPrepaid) { // Send receipt for PrePaid // No tolls and surcharge for prepaid orders SendTripReceipt(@event.SourceId, Convert.ToDecimal(@event.Fare ?? 0), Convert.ToDecimal(@event.Tip ?? 0), Convert.ToDecimal(@event.Tax ?? 0)); } else { var order = _orderDao.FindById(@event.SourceId); var pairingInfo = _orderDao.FindOrderPairingById(@event.SourceId); var orderStatus = _orderDao.FindOrderStatusById(@event.SourceId); if (CmtErrorCodes.IsTerminalError(orderStatus.PairingError)) { return; } if (order.Settings.ChargeTypeId == ChargeTypes.PaymentInCar.Id) { // Send receipt for Pay in Car SendTripReceipt(@event.SourceId, Convert.ToDecimal(@event.Fare ?? 0), Convert.ToDecimal(@event.Tip ?? 0), Convert.ToDecimal(@event.Tax ?? 0), toll: Convert.ToDecimal(@event.Toll ?? 0), surcharge: Convert.ToDecimal(@event.Surcharge ?? 0)); } else if (pairingInfo != null && pairingInfo.DriverId.HasValue() && pairingInfo.Medallion.HasValue() && pairingInfo.PairingToken.HasValue()) { // Send receipt for CMTRideLinq InitializeCmtServiceClient(order.CompanyKey); var tripInfo = _cmtTripInfoServiceHelper.GetTripInfo(pairingInfo.PairingToken); if (tripInfo != null && !tripInfo.ErrorCode.HasValue && tripInfo.EndTime.HasValue) { var tollHistory = tripInfo.TollHistory != null ? tripInfo.TollHistory.Sum(p => p.TollAmount) : 0; var meterAmount = Math.Round(((double)tripInfo.Fare / 100), 2); var tollAmount = Math.Round(((double)tollHistory / 100), 2); var tipAmount = Math.Round(((double)tripInfo.Tip / 100), 2); var taxAmount = Math.Round(((double)tripInfo.Tax / 100), 2); var surchargeAmount = Math.Round(((double)tripInfo.Surcharge / 100), 2); var extraAmount = Math.Round(((double)tripInfo.Extra / 100), 2); var accessFee = Math.Round(((double)tripInfo.AccessFee / 100), 2); var fareAtAlternateRate = Math.Round(((double)tripInfo.FareAtAlternateRate / 100), 2); var tolls = new List <TollDetail>(); if (tripInfo.TollHistory != null) { tolls.AddRange(tripInfo.TollHistory.Select(toll => new TollDetail { TollName = toll.TollName, TollAmount = toll.TollAmount })); } SendTripReceipt(@event.SourceId, Convert.ToDecimal(meterAmount), Convert.ToDecimal(tipAmount), Convert.ToDecimal(taxAmount), extra: Convert.ToDecimal(extraAmount), toll: Convert.ToDecimal(tollAmount), surcharge: Convert.ToDecimal(surchargeAmount), cmtRideLinqFields: new SendReceipt.CmtRideLinqReceiptFields { DriverId = tripInfo.DriverId.ToString(), PickUpDateTime = tripInfo.StartTime, DropOffDateTime = tripInfo.EndTime, TripId = tripInfo.TripId, Distance = tripInfo.Distance, LastFour = tripInfo.LastFour, AccessFee = accessFee, FareAtAlternateRate = fareAtAlternateRate, RateAtTripEnd = tripInfo.RateAtTripEnd, RateAtTripStart = tripInfo.RateAtTripStart, Tolls = tolls.ToArray(), TipIncentive = order.TipIncentive ?? 0 }); } } } } }