private XmlNode BuildOrderXml(XmlDocument xmlDocument, Order order, RenderOrderSettings settings) { var tableNode = CreateTableNode(xmlDocument, "EcomOrders"); var itemNode = CreateAndAppendItemNode(tableNode, "EcomOrders"); var user = User.GetUserByID(order.CustomerAccessUserId) ?? (!ExecutingContext.IsBackEnd() ? User.GetCurrentExtranetUser() : null); // do not use order.Modified in XML unless the field can be ignored for hash calculation // in the current version of NAV for vanBaerle, the calculation is made using the ExternalId field name but the logic corresonds to the customer number in DynamicWeb //AddChildXmlNode(itemNode, "OrderCustomerAccessUserExternalId", !string.IsNullOrWhiteSpace(user?.ExternalID) ? user.ExternalID : Settings.Instance.AnonymousUserKey); AddChildXmlNode(itemNode, "OrderCustomerAccessUserExternalId", !string.IsNullOrWhiteSpace(user?.CustomerNumber) ? user.CustomerNumber : Settings.Instance.AnonymousUserKey); AddChildXmlNode(itemNode, "OrderCustomerNumber", !string.IsNullOrWhiteSpace(user?.CustomerNumber) ? user.CustomerNumber : Settings.Instance.AnonymousUserKey); AddChildXmlNode(itemNode, "CreateOrder", settings.CreateOrder.ToString()); AddChildXmlNode(itemNode, "OrderId", order.Id); AddChildXmlNode(itemNode, "OrderAutoId", order.AutoId.ToString()); AddChildXmlNode(itemNode, "OrderIntegrationOrderId", order.IntegrationOrderId); AddChildXmlNode(itemNode, "OrderCurrencyCode", order.CurrencyCode); AddChildXmlNode(itemNode, "OrderDate", order.Date.ToIntegrationString()); AddChildXmlNode(itemNode, "OrderPaymentMethodName", order.PaymentMethod, true); AddChildXmlNode(itemNode, "OrderPaymentMethodId", order.PaymentMethodId); AddChildXmlNode(itemNode, "OrderShippingMethodName", order.ShippingMethod, true); AddChildXmlNode(itemNode, "OrderShippingMethodId", order.ShippingMethodId); AddChildXmlNode(itemNode, "OrderShippingFee", order.ShippingFee.PriceWithoutVAT.ToIntegrationString()); AddChildXmlNode(itemNode, "OrderCustomerName", order.CustomerName); AddChildXmlNode(itemNode, "OrderCustomerAddress", order.CustomerAddress); AddChildXmlNode(itemNode, "OrderCustomerAddress2", order.CustomerAddress2); AddChildXmlNode(itemNode, "OrderCustomerCity", order.CustomerCity); AddChildXmlNode(itemNode, "OrderCustomerState", order.CustomerRegion); AddChildXmlNode(itemNode, "OrderCustomerZip", order.CustomerZip); AddChildXmlNode(itemNode, "OrderCustomerCountryCode", order.CustomerCountryCode); AddChildXmlNode(itemNode, "OrderCustomerEmail", order.CustomerEmail); AddChildXmlNode(itemNode, "OrderCustomerPhone", order.CustomerPhone); AddChildXmlNode(itemNode, "OrderCustomerFax", order.CustomerFax); AddChildXmlNode(itemNode, "OrderDeliveryName", !string.IsNullOrWhiteSpace(order.DeliveryName) ? order.DeliveryName : order.CustomerName); AddChildXmlNode(itemNode, "OrderDeliveryAddress", order.DeliveryAddress); AddChildXmlNode(itemNode, "OrderDeliveryAddress2", order.DeliveryAddress2); AddChildXmlNode(itemNode, "OrderDeliveryCity", order.DeliveryCity); AddChildXmlNode(itemNode, "OrderDeliveryState", order.DeliveryRegion); AddChildXmlNode(itemNode, "OrderDeliveryZip", order.DeliveryZip); AddChildXmlNode(itemNode, "OrderDeliveryCountryCode", order.DeliveryCountryCode); AddChildXmlNode(itemNode, "OrderDeliveryEmail", order.DeliveryEmail); AddChildXmlNode(itemNode, "OrderDeliveryPhone", order.DeliveryPhone); AddChildXmlNode(itemNode, "OrderDeliveryFax", order.DeliveryFax); AddChildXmlNode(itemNode, "OrderCustomerComment", order.CustomerComment); AddChildXmlNode(itemNode, "OrderPriceTotal", order.TotalPrice.ToIntegrationString()); AddChildXmlNode(itemNode, "OrderCaptureAmount", order.CaptureAmount.ToIntegrationString()); AddChildXmlNode(itemNode, "OrderVoucherCode", order.VoucherCode); AddChildXmlNode(itemNode, "OrderTransactionId", order.TransactionNumber); AddChildXmlNode(itemNode, "OrderStateId", order.StateId); AddChildXmlNode(itemNode, "OrderStateName", order.OrderState.Name, true); CreditCardGatewayResult paymentInformation = ReadPaymentInformation(order); AddChildXmlNode(itemNode, "OrderTransactionCardType", paymentInformation.Type, true); AddChildXmlNode(itemNode, "OrderTransactionCardExpiryDate", paymentInformation.ExpiryDate, true); AddChildXmlNode(itemNode, "OrderTransactionMaskedCreditCardNumber", paymentInformation.Number, true); AddChildXmlNode(itemNode, "CardHolderFirstName", paymentInformation.FirstName, true); AddChildXmlNode(itemNode, "CardholderLastName", paymentInformation.LastName, true); if (settings.AddOrderFieldsToRequest) { AppendOrderFields(order, itemNode); } return(tableNode); }
/// <summary> /// Updates an order in the ERP. /// </summary> /// <param name="order">The order that must be synced with the ERP.</param> /// <param name="liveIntegrationSubmitType">Determines the origin of this submit such.</param> /// <param name="successOrderStateId">The order state that is applied to the order when it integrates successfully.</param> /// <param name="failedOrderStateId">The order state that is applied to the order when an error occurred during the integration.</param> /// <returns>Returns null if no communication has made, or bool if order has been updated successfully or not.</returns> public static bool?UpdateOrder(Order order, LiveIntegrationSubmitType liveIntegrationSubmitType, string successOrderStateId = null, string failedOrderStateId = null) { if (order == null || !order.OrderLines.Any()) { return(null); } if (liveIntegrationSubmitType == LiveIntegrationSubmitType.LiveOrderOrCart && !string.IsNullOrEmpty(order.IntegrationOrderId)) { return(null); } var orderId = order.Id ?? "ID is null"; Logger.Instance.Log(ErrorLevel.DebugInfo, string.Format("Updating order with ID: {0}. Complete: {1}. Order submitted from the backend: {2}. Stack trace: {3}", orderId, order.Complete, ExecutingContext.IsBackEnd(), Environment.StackTrace)); // use current user if is not backend running or if the cart is Anonymous var user = (order.CustomerAccessUserId > 0 ? User.GetUserByID(order.CustomerAccessUserId) : null) ?? (!ExecutingContext.IsBackEnd() ? User.GetCurrentExtranetUser() : null); // customization for VanBaerle branch: ERP doesn't support anonymous users and throws errors if (user == null) { return(null); } /* create order: if it is false, you will get a calculate order from the ERP with the total prices */ /* if it is true, then a new order will be created in the ERP */ bool createOrder = order.Complete; if (createOrder && user != null) { UserSync(user); } if (!Settings.Instance.EnableCartCommunicationForAnonymousUsers && user == null) { Logger.Instance.Log(ErrorLevel.DebugInfo, string.Format("No user is currently logged in. Anonymous user cart is not allowed. Order = {0}", orderId)); return(null); } // default states if (successOrderStateId == null) { successOrderStateId = Settings.Instance.OrderStateAfterExportSucceeded; } if (failedOrderStateId == null) { failedOrderStateId = Settings.Instance.OrderStateAfterExportFailed; } var requestXml = new OrderXmlRenderer().RenderOrderXml(order, new RenderOrderSettings { AddOrderLineFieldsToRequest = AddOrderLineFieldsToRequest, AddOrderFieldsToRequest = AddOrderFieldsToRequest, CreateOrder = createOrder, LiveIntegrationSubmitType = liveIntegrationSubmitType, ReferenceName = "OrdersPut" }); if (createOrder && SaveOrderXml && liveIntegrationSubmitType == LiveIntegrationSubmitType.LiveOrderOrCart) { SaveCopyOfXml(order.Id, requestXml); } // calculate current hash string currentHash = CalculateHash(requestXml); // get last hash string lastHash = GetLastOrderHash(); if (!string.IsNullOrEmpty(lastHash) && lastHash == currentHash) { // no changes to order return(null); } // save this hash for next calls SaveOrderHash(currentHash); // clear all session var to avoid miss calculations HttpContext.Current.Session.Remove("LiveIntegrationDiscounts" + order.Id); Dictionary <string, XmlDocument> responsesCache = ErpResponseCache.GetWebOrdersConnectorResponses(OrderCacheLevel); XmlDocument response = null; if (!createOrder && responsesCache.ContainsKey(requestXml)) { response = responsesCache[requestXml]; } else { if (createOrder) { OrderDebuggingInfo.Save(order, "Sending order to the ERP system through Live Integration.", "OrderHandler"); } try { response = Connector.CalculateOrder(requestXml, order.Id, createOrder); } catch (LiveIntegrationException ex) { // TODO Rui, handle appropriately Logger.Instance.Log(ErrorLevel.ConnectionError, ex.Message); } if (responsesCache.ContainsKey(requestXml)) { responsesCache.Remove(requestXml); } if (!string.IsNullOrWhiteSpace(response?.InnerXml)) { responsesCache.Add(requestXml, response); } } if (!string.IsNullOrWhiteSpace(response?.InnerXml)) { bool processResponseResult = ProcessResponse(response, order, createOrder, successOrderStateId, failedOrderStateId); // new user sync active, sync user (Update) if (Settings.Instance.UpdateUserAfterNewOrder && user != null) { user.SynchronizeUsingLiveIntegration(true, UserSyncMode.Get); } return(processResponseResult); } else { //error occurred CheckIfOrderShouldRevertToCart(order, createOrder); return(false); } }