/// <summary> /// Updates an order /// </summary> /// <param name="dbOrder">The order</param> /// <exception cref="ApplicationException">Order: [{order.OrderGuid}] is not valid</exception> internal async Task UpdateOrderAsync(OrderDBE dbOrder) { // turn off change tracking since we are going to overwite the entity // Note: I would not do this if there was a db assigned unique id for the record this.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; var currentOrder = await this.Orders.SingleOrDefaultAsync(o => o.OrderGuid == dbOrder.OrderGuid); if (currentOrder == null) { throw new ApplicationException($"Order: [{dbOrder.OrderGuid}] is not valid"); } this.Update(dbOrder); try { await this.SaveChangesAsync(); } catch (DbUpdateException ex) { // exception was raised by the db (ex: UK violation) var sqlException = ex.InnerException; // we do this to disconnect the exception that bubbles up from the dbcontext which will be disposed when it leaves this method throw new ApplicationException(sqlException.Message); } catch (Exception) { // rethrow exception throw; } }
private static MerchantOrderMBE BuildExplodedMerchantOrderMBE(OrderDBE dbExplodedOrder) { // convert DB entity to the public entity type var order = (MerchantOrderMBE)dbExplodedOrder; order.MerchantGuid = dbExplodedOrder.Merchant.MerchantGuid; //create an empty working object var catalogItems = new List <CatalogItemMBE>(); var orderEvents = new List <OrderEventMBE>(); // optionally convert DB entities to the public entity type if (dbExplodedOrder.OrderLineItems != null) { // convert DB entities to the public entity types catalogItems = dbExplodedOrder.OrderLineItems.ConvertAll(oli => (CatalogItemMBE)oli); } if (dbExplodedOrder.OrderEvents != null) { // convert DB entities to the public entity types orderEvents = dbExplodedOrder.OrderEvents.ConvertAll(dbE => (OrderEventMBE)dbE); } // set the value of the property collection on the parent object order.OrderLineItems = catalogItems; order.OrderEvents = orderEvents; return(order); }
private async Task <OrderDBE> InsertNewExplodedOrderAsync(int merchantId, NewOrderMBE newExplodedOrder, int?refOrderId = null) { //Step 1: Store the new merchant Order var newDBOrder = new OrderDBE() { Status = Enums.ORDER_STATUS.New, MerchantId = merchantId, CustomerName = newExplodedOrder.CustomerName, PhoneNumber = newExplodedOrder.CustomerPhoneNo, OrderDateTimeUTC = DateTime.UtcNow, RefOrderId = refOrderId }; await _dbContext.InsertOrderAsync(newDBOrder); //Step 2: create the first event var newDBOrderEvent = new OrderEventDBE() { OrderId = newDBOrder.OrderId, EventDateTimeUTC = DateTime.UtcNow, OrderStatus = Enums.ORDER_STATUS.New, EventDescription = refOrderId.HasValue ? $"Order created (from {refOrderId.Value})." : "Order created" }; await _dbContext.InsertOrderEventAsync(newDBOrderEvent); //newDBOrder.OrderEvents.Add(newDBOrderEvent); // build exploded order //Step 3: iterate through orderLineItems collection to save it in the db foreach (var orderLineItem in newExplodedOrder.OrderLineItems) { var catalogItem = await _dbContext.GetCatalogItemAsync(orderLineItem.ItemGuid); var newDBOrderLineItem = new OrderLineItemDBE() { ItemName = catalogItem.ItemName, ItemUnitPrice = catalogItem.ItemUnitPrice, OrderId = newDBOrder.OrderId, CatalogItemGuid = orderLineItem.ItemGuid }; await _dbContext.InsertOrderLineItemAsync(newDBOrderLineItem); //newDBOrder.OrderLineItems.Add(newDBOrderLineItem); // build exploded order } return(newDBOrder); }
private async Task SendSMSMessageAsync(OrderDBE dbOrderExploded, WebUrlConfigurationBE webUrlConfig) { // Step 1: calc the order total decimal orderTotal = (dbOrderExploded.OrderLineItems != null) ? dbOrderExploded.OrderLineItems.Sum(oli => oli.ItemUnitPrice) : 0.0M; // Step 2: Build the SMS Msg string payAwayURL = $"{webUrlConfig.HPPBaseUrl}/customerorder/{dbOrderExploded.OrderGuid}"; StringBuilder messageBody = new StringBuilder(); messageBody.AppendLine($"Hello {dbOrderExploded.CustomerName}"); // we do not know what culture the server is set for so we are explicit, we want to make it formats currency with a US $ var specificCulture = System.Globalization.CultureInfo.GetCultureInfo("en-US"); FormattableString formattableString = $"{dbOrderExploded.Merchant.MerchantName} is sending you this link to a secure payment page to enter your payment info for your Order Number: {dbOrderExploded.OrderId:0000} for: {orderTotal:C}"; messageBody.AppendLine(formattableString.ToString(specificCulture)); messageBody.AppendLine($"{payAwayURL}"); // Step 3: Send the SMS msg // convert the phone no to the "normalized format" +15131234567 that the SMS api accepts (bool isValidPhoneNo, string formattedPhoneNo, string normalizedPhoneNo) = Utilities.PhoneNoHelpers.NormalizePhoneNo(dbOrderExploded.PhoneNumber); var msgSid = SMSController.SendSMSMessage(String.Empty, formattedPhoneNo, messageBody.ToString()); // Step 4 Create & Save the SMS event var dbOrderEvent = new OrderEventDBE() { OrderId = dbOrderExploded.OrderId, EventDateTimeUTC = DateTime.UtcNow, OrderStatus = Enums.ORDER_STATUS.SMS_Sent, EventDescription = $"SMS sent to [{normalizedPhoneNo}]." }; await _dbContext.InsertOrderEventAsync(dbOrderEvent); // Step 5: Update the order status dbOrderExploded.Status = Enums.ORDER_STATUS.SMS_Sent; await _dbContext.UpdateOrderAsync(dbOrderExploded); }
/// <summary> /// Inserts new order /// </summary> /// <param name="newOrder">The new order</param> /// <returns>A new order.</returns> /// <remarks> /// only used by the ResetDB method so we can keep the same guids across reloads. /// </remarks> internal async Task InsertOrderAsync(OrderDBE newOrder) { this.Orders.Add(newOrder); try { await this.SaveChangesAsync(); } catch (DbUpdateException ex) { // exception was raised by the db (ex: UK violation) var sqlException = ex.InnerException; // we do this to disconnect the exception that bubbles up from the dbcontext which will be disposed when it leaves this method throw new ApplicationException(sqlException.Message); } catch (Exception) { // rethrow exception throw; } }