/// <summary>
 /// Cancels or backorders the items in an existing order.
 /// </summary>
 /// <param name="args">The args.</param>
 /// <param name="cancel">if set to <c>true</c> [cancel] else backorder</param>
 /// <returns>{error:0,desc:""}</returns>
 private static Dictionary<string, object> CancelBackorderItems(List<object> args, bool cancel)
 {
     /*TODO: backorder procedure has uncertain payment stuff going on here
      * cancel works, backorder works, but changing
      *
      */
     Dictionary<string, object> j = new Dictionary<string, object>();
     using(SqlConnection cn = Site.CreateConnection(true, true)) {
         cn.Open();
         using(SqlTransaction cancelBackorderTransaction = cn.BeginTransaction("Backorder or Cancel")) {
             bool rollback = true;
             try {
                 foreach(object line in args) {
                     Dictionary<string, object> fields = (Dictionary<string, object>)line;
                     // never used -->Dictionary<string,object> flag;
                     if(!fields.ContainsKey("serialId") || !fields.ContainsKey("qty")) {
                         Exception e = new Exception("key serialId or qty is missing");
                         throw e;
                     }
                     int serialId = Convert.ToInt32(fields["serialId"].ToString());
                     int qty = Convert.ToInt32(fields["qty"].ToString());
                     /* update the cart table with the number of items to be backordered.   */
                     using(SqlCommand cmd = new SqlCommand("update cart set returnToStock = @return where serialId = @serialId", cn, cancelBackorderTransaction)) {
                         cmd.Parameters.Add("@serialId", SqlDbType.Int).Value = serialId;
                         cmd.Parameters.Add("@return", SqlDbType.Int).Value = qty;
                         cmd.ExecuteNonQuery();
                     }
                     /* now add the flag that will trigger serial_line.TR_LINE_DEPLETE_INVENTORY*/
                     /* flag -11 is backorder, flag -12 is cancel */
                     using(SqlCommand cmd = new SqlCommand("dbo.backorderCancel @serialId,@cancel,@backorder", cn, cancelBackorderTransaction)) {
                         cmd.Parameters.Add("@serialId", SqlDbType.Int).Value = serialId;
                         cmd.Parameters.Add("@cancel", SqlDbType.Bit).Value = cancel;
                         cmd.Parameters.Add("@backorder", SqlDbType.Bit).Value = !cancel;
                         cmd.ExecuteNonQuery();
                     }
                     /* if this is a cancelation don't create a new order or add to an existing order */
                     if(cancel) {
                         AddFlagWithTransaction("0", "line", serialId.ToString(), "Quantity of " + qty + " canceled", cn, cancelBackorderTransaction);
                     } else {
                         /* first check to see if an order is already the child of this order
                             * if so, then just add this item to the child order (backorder)
                             * if there is no child order than create the child order now.
                             */
                         Commerce.Order childOrder;
                         List<Commerce.Order> childOrders = Commerce.Order.GetChildOrdersBySerialId(serialId, cn, cancelBackorderTransaction);
                         if(childOrders.Count == 0) {
                             childOrder = null;
                         } else {
                             childOrder = childOrders[0];
                         }
                         Commerce.Order order = Commerce.Order.GetOrderBySerialId(serialId, cn, cancelBackorderTransaction);
                         if(childOrder == null) {
                             /* create a new order and add the item's qty to the new order */
                             /* get the line that will be added to the backorder */
                             List<Commerce.Line> sourceLines = order.Lines.FindAll(delegate(Commerce.Line ln) {
                                 return ln.SerialId == serialId && ln.KitAllocationCartId == ln.CartId;
                             });
                             /* sort the items by int kitAllocationId */
                             sourceLines.Sort(delegate(Commerce.Line l1, Commerce.Line l2) {
                                 return l1.KitAllocationId.CompareTo(l2.KitAllocationId);
                             });
                             /* when there is more than one source line, always pick the one with the larget id
                                 * this will be the parent/virtual item that needs to be added to the backorder */
                             Commerce.Line sourceLine = sourceLines[sourceLines.Count - 1];
                             /* create a new session for the new order */
                             Session session = new Session(Main.Site, cn, cancelBackorderTransaction);
                             Site.LogOn(order.UserId, session, cn, cancelBackorderTransaction);
                             session.Refresh(false, cn, cancelBackorderTransaction);
                             AddToCartArguments addTocartArgs = new AddToCartArguments();
                             addTocartArgs["itemNumber"] = sourceLine.ItemNumber;
                             addTocartArgs["qty"] = fields["qty"].ToString();
                             addTocartArgs["customerLineNumber"] = sourceLine.CustomLineNumber;
                             addTocartArgs["sessionId"] = session.Id.ToString();
                             addTocartArgs["price"] = sourceLine.Price;
                             addTocartArgs["allowPreorder"] = true;
                             /* add all of the inputs as arguments */
                             Dictionary<string, object> addToCartArgs = Cart.AddToCart(addTocartArgs, cn, cancelBackorderTransaction);
                             if(Convert.ToInt32(addToCartArgs["error"]) != 0) {
                                 Exception e = new Exception(addToCartArgs["description"].ToString());
                                 throw e;
                             }
                             Guid newCartId = new Guid(addToCartArgs["cartId"].ToString());
                             /* copy all of the order header data into the new order */
                             using(SqlCommand cmd = new SqlCommand("dbo.duplicateCartDetail @sourceCartId,@targetCartId", cn, cancelBackorderTransaction)) {
                                 cmd.Parameters.Add("@sourceCartId", SqlDbType.UniqueIdentifier).Value = new Guid(sourceLine.CartId.ToString());
                                 cmd.Parameters.Add("@targetCartId", SqlDbType.UniqueIdentifier).Value = new Guid(newCartId.ToString());
                                 cmd.ExecuteNonQuery();
                             }
                             OrderArguments newOrderArgs = new OrderArguments();
                             newOrderArgs["billToFirstName"] = order.BillToAddress.FirstName;
                             newOrderArgs["billToLastName"] = order.BillToAddress.LastName;
                             newOrderArgs["billToAddress1"] = order.BillToAddress.Address1;
                             newOrderArgs["billToAddress2"] = order.BillToAddress.Address2;
                             newOrderArgs["billToCity"] = order.BillToAddress.City;
                             newOrderArgs["billToState"] = order.BillToAddress.State;
                             newOrderArgs["billToZip"] = order.BillToAddress.Zip;
                             newOrderArgs["billToCountry"] = order.BillToAddress.Country;
                             newOrderArgs["billToHomePhone"] = order.BillToAddress.HomePhone;
                             newOrderArgs["billToWorkPhone"] = order.BillToAddress.WorkPhone;
                             newOrderArgs["billToCompany"] = order.BillToAddress.Company;
                             newOrderArgs["billToComments"] = order.BillToAddress.Comments;
                             newOrderArgs["billToSpecialInstructions"] = order.BillToAddress.SpecialInstructions;
                             newOrderArgs["billToSendShipmentUpdates"] = order.BillToAddress.SendShipmentUpdates;
                             newOrderArgs["FOB"] = order.FOB;
                             newOrderArgs["termId"] = order.TermId;
                             newOrderArgs["userId"] = session.User.UserId;
                             newOrderArgs["manifestNumber"] = order.Manifest;
                             newOrderArgs["purchaseOrder"] = Utilities.Iif(order.PurchaseOrder.Length > 0, order.PurchaseOrder + ">" + order.OrderNumber, "");
                             newOrderArgs["sessionId"] = session.Id.ToString();
                             newOrderArgs["shipToRateId"] = -1;/* never put a shipping method on backorders */
                             newOrderArgs["billToRateId"] = -1;
                             newOrderArgs["shipToEmailAds"] = false;
                             newOrderArgs["billToEmailAds"] = false;
                             newOrderArgs["billToSendShipmentUpdates"] = false;
                             newOrderArgs["shipToFirstName"] = order.ShipToAddress.FirstName;
                             newOrderArgs["shipToLastName"] = order.ShipToAddress.LastName;
                             newOrderArgs["shipToAddress1"] = order.ShipToAddress.Address1;
                             newOrderArgs["shipToAddress2"] = order.ShipToAddress.Address2;
                             newOrderArgs["shipToCity"] = order.ShipToAddress.City;
                             newOrderArgs["shipToState"] = order.ShipToAddress.State;
                             newOrderArgs["shipToZip"] = order.ShipToAddress.Zip;
                             newOrderArgs["shipToCountry"] = order.ShipToAddress.Country;
                             newOrderArgs["shipToHomePhone"] = order.ShipToAddress.HomePhone;
                             newOrderArgs["shipToWorkPhone"] = order.ShipToAddress.WorkPhone;
                             newOrderArgs["shipToCompany"] = order.ShipToAddress.Company;
                             newOrderArgs["shipToComments"] = order.ShipToAddress.Comments;
                             newOrderArgs["shipToSpecialInstructions"] = order.ShipToAddress.SpecialInstructions;
                             newOrderArgs["shipToSendShipmentUpdates"] = order.ShipToAddress.SendShipmentUpdates;
                             newOrderArgs["parentOrderId"] = order.OrderId;
                             newOrderArgs["comments"] = "This order is a backorder from Order " + order.OrderNumber;
                             newOrderArgs.Add("backorder", true);
                             /* place the new backorder */
                             Dictionary<string, object> newOrder = Commerce.Order.PlaceOrderWithTransaction(newOrderArgs, cn, cancelBackorderTransaction);
                             if(Convert.ToInt32(newOrder["error"]) != 0) {
                                 Exception e = new Exception(newOrder["description"].ToString());
                                 throw e;
                             }
                             childOrder = Commerce.Order.GetOrderByOrderNumber((string)newOrder["orderNumber"], cn, cancelBackorderTransaction);
                             j.Add("childOrder", childOrder.GetOrderJson());
                         } else {
                             /* the child order (backorder) already existed, so add the item to the backorder */
                             Commerce.Line sourceLine = order.Lines.Find(delegate(Commerce.Line ln) {
                                 return ln.SerialId == serialId;
                             });
                             /* create a new session for the new order */
                             Session session = new Session(Main.Site, cn, cancelBackorderTransaction);
                             Site.LogOn(childOrder.UserId, session, cn, cancelBackorderTransaction);
                             session.Refresh(false, cn, cancelBackorderTransaction);
                             AddToCartArguments addTocartArgs = new AddToCartArguments();
                             addTocartArgs["itemNumber"] = sourceLine.ItemNumber;
                             addTocartArgs["qty"] = fields["qty"].ToString();
                             addTocartArgs["customerLineNumber"] = sourceLine.CustomLineNumber;
                             addTocartArgs["sessionId"] = session.Id.ToString();
                             addTocartArgs["addressId"] = sourceLine.AddressId.ToString();
                             addTocartArgs["price"] = sourceLine.Price;
                             addTocartArgs["allowPreorder"] = true;
                             /* add all of the inputs as arguments */
                             Dictionary<string, object> addToCartArgs = Cart.AddToCart(addTocartArgs, cn, cancelBackorderTransaction);
                             if(Convert.ToInt32(addToCartArgs["error"]) != 0) {
                                 Exception e = new Exception(addToCartArgs["description"].ToString());
                                 throw e;
                             }
                             Guid newCartId = new Guid(addToCartArgs["cartId"].ToString());
                             /* copy all of the order header data into the new order */
                             using(SqlCommand cmd = new SqlCommand("dbo.duplicateCartDetail @sourceCartId,@targetCartId", cn, cancelBackorderTransaction)) {
                                 cmd.Parameters.Add("@sourceCartId", SqlDbType.UniqueIdentifier).Value = new Guid(sourceLine.CartId.ToString());
                                 cmd.Parameters.Add("@targetCartId", SqlDbType.UniqueIdentifier).Value = new Guid(newCartId.ToString());
                                 cmd.ExecuteNonQuery();
                             }
                             Dictionary<string, object> recalculateArgs = new Dictionary<string, object>();
                             recalculateArgs.Add("userId", childOrder.UserId);
                             recalculateArgs.Add("orderSessionId", childOrder.SessionId.ToString());
                             recalculateArgs.Add("cartSessionId", session.Id.ToString());
                             recalculateArgs.Add("cardType", "");
                             recalculateArgs.Add("cardNumber", "");
                             recalculateArgs.Add("expMonth", "");
                             recalculateArgs.Add("expYear", "");
                             recalculateArgs.Add("secNumber", "");
                             recalculateArgs.Add("nameOnCard", "");
                             recalculateArgs.Add("billToAddressId", childOrder.BillToAddress.Id.ToString());
                             recalculateArgs.Add("shipToAddressId", childOrder.ShipToAddress.Id.ToString());
                             recalculateArgs.Add("preview", false);
                             recalculateArgs.Add("purchaseOrder", childOrder.PurchaseOrder);
                             recalculateArgs.Add("backorder", true);
                             Dictionary<string, object> recalculatedOrder = RecalculateOrder(recalculateArgs, cn, cancelBackorderTransaction);
                             if((int)recalculatedOrder["error"] != 0) {
                                 Exception e = new Exception(recalculatedOrder["description"].ToString());
                                 throw e;
                             }
                             Commerce.Order _order = Commerce.Order.GetOrderByOrderNumber((string)recalculatedOrder["orderNumber"], cn, cancelBackorderTransaction);
                             j.Add("childOrder", _order.GetOrderJson());
                         }
                         AddFlagWithTransaction("0", "line", serialId.ToString(), "Quantity of " + qty + " added to backorder " + childOrder.OrderNumber, cn, cancelBackorderTransaction);
                     }
                 }
                 rollback = false;
                 cancelBackorderTransaction.Commit();
                 j.Add("error", 0);
                 j.Add("description", "");
             } catch(Exception e) {
                 rollback = true;
                 j.Add("error", -1);
                 j.Add("description", e.Message);
             } finally {
                 if(rollback) {
                     cancelBackorderTransaction.Rollback();
                 }
             }
         }
     }
     return j;
 }
        /// <summary>
        /// Process JSON messages.
        /// Map some messages to methods.
        /// Map some messages to embedded resources.
        /// Secondary HTTP Pipeline.
        /// </summary>
        /// <param name="httpApp">The Http app.</param>
        /// <returns>When true, a AJAX responder was called</returns>
        private static bool processHTTPRequest(HttpApplication httpApp)
        {
            /* get the current http context */
            bool _JSONResponse = false;
            HttpContext current = HttpContext.Current;
            /* start a Timer */
            DateTime startHTTPRequest = DateTime.Now;
            current.Items.Add("startHTTPRequest", startHTTPRequest);
            /* create a reference to the session object */
            Session session = null;
            string executionFilePath = current.Request.AppRelativeCurrentExecutionFilePath;
            bool _isVirtualResourcePath = IsVirtualResourcePath(executionFilePath);
            /* ***1*** make sure user's don't request an invalid file resource by redirecting */
            if(Main.AdminDirectory == executionFilePath) {
                current.Response.Redirect(Main.AdminDirectory + "/", false);
                current.ApplicationInstance.CompleteRequest();
                goto End;
            }
            /* ***2*** if this is not a request for a /Admin or /responder directory
             * implement the rewriter directives */
            if(!_isVirtualResourcePath) {
                /* try to redirect the URL */
                if(redirectUrl(current)) { goto End; };
                /* try to rewrite the URL */
                if(RewriteUrl(current)) { goto End; };
                /* site section rewrites */
                if(RewriteSiteSection(current)) { goto End; };
                /* check for category rewrites */
                if(RewriteCategory(current)) { goto End; };
                /* check for item rewrites */
                if(RewriteItem(current)) { goto End; };
            }
            /* ***3*** don't try and examine the physical path until _after_ the rewrite */
            string physicalPath = current.Request.PhysicalPath;
            bool _isResourceFile = IsResourceFile(physicalPath);

            /* if this is an image or other non dynamic resource file
             * and not used in a virtual path than don't do any further processing */
            if(_isResourceFile && !_isVirtualResourcePath) {
                sendNeverExpiresHeaders();
                goto End;
            }
            /* if this is a public resource, give up the resource now */
            foreach(string file in Main.PublicFiles) {
                if(executionFilePath == file || executionFilePath.StartsWith(Main.AdminDirectory + "/img")) {
                    sendNeverExpiresHeaders();
                    getResxResource(current);
                    goto End;
                }
            }
            /* no rewrite or redirect so now check if the file exists */
            if(!File.Exists(physicalPath) && !_isVirtualResourcePath) {
                ErrorPage(current, 404, String.Format("Cannot find {0}", physicalPath));
                goto End;
            }
            /* the file or resource exists (probably)
             * create a Session
             * this is resource consuming */
            session = new Session(Site);
            /* place the session object in an object that is only good as long as the http pipeline lasts */
            current.Items.Add("currentSession", session);
            /* raise the after authentication event */
            AfterAuthenticationEventArgs args = new AfterAuthenticationEventArgs(session, current);
            Main.Site.raiseOnAfterAuthentication(args);
            /* execute AJAX responders - if a responder was executed then end. */
            try {
                if(executeResponders(current, session)) {
                    _JSONResponse = true;
                    goto End;
                };
            } catch(Exception ex) {
                String.Format("executeResponders exception =>{0}", ex.Message).Debug(0);
                goto End;
            }
            /* check if this is a request for the Admin directory or Admin responder virtual page */
            if(_isVirtualResourcePath) {
                /* don't do anything for people who arn't logged on as administrators, unless we're in setup mode */
                if(!session.Administrator) {
                    /* 401 forbidden, and ask for a username / password */
                    /* RFC 2617 HTTP Authentication: Basic and Digest Access Authentication */
                    if(current.Request.Headers["Authorization"] != null) {
                        /* user is sending logon attempt via HTTP auth */
                        string _raw_header = current.Request.Headers["Authorization"];
                        string[] _hprams = _raw_header.Split(' ');
                        string method = _hprams[0];
                        string enc_auth = _hprams[1];
                        /* decode base 64 auth string */
                        string _raw_auth = Encoding.ASCII.GetString(Convert.FromBase64String(enc_auth));
                        string[] _auth = _raw_auth.Split(':');
                        string userName = _auth[0];
                        string password = _auth[1];
                        /* try to logon using the provided authentication creditials */
                        if(session.LogOn(userName, password) == 0) {
                            session.Refresh();
                        }
                    }
                    /* check again */
                    if(!session.Administrator) {
                        if(!UseFormsBasedAuth) {
                            current.Response.AddHeader("WWW-Authenticate", String.Format("Basic realm=\"{0}\"", current.Request.Url.DnsSafeHost));
                            ErrorPage(current, 401,
                            String.Format("Only administrators can access the {0} virtual directory.", Main.AdminDirectory));/* 401 unauthorized */
                            current.ApplicationInstance.CompleteRequest();
                            goto End;
                        } else {
                            current.Response.Redirect(Main.PublicDirectory + "/logon.html?rdr=" + executionFilePath.UrlEncode());
                            current.ApplicationInstance.CompleteRequest();
                            goto End;
                        }
                    }
                }
                sendNeverExpiresHeaders();
                /* if this is a request for the Admin directory tree respond with the given Admin resource */
                if(!executionFilePath.Contains(Main.AdminResponder)) {
                    getResxResource(current);
                    goto End;
                }
            }
            End:
            /* fire off events */
            EndRequestEventArgs endRequestargs = new EndRequestEventArgs(session, current);
            Site.raiseOnendrequest(endRequestargs);
            DateTime endHTTPRequest = DateTime.Now;
            current.Items.Add("finish_processHTTPRequest", endHTTPRequest);
            return _JSONResponse;
        }