Esempio n. 1
0
        /// <summary>
        /// Places the order.
        /// </summary>
        protected void PlaceOrder()
        {
            MergeShipment();

            // Make sure to execute within transaction
            using (var scope = new Mediachase.Data.Provider.TransactionScope())
            {
                try
                {
                    OrderGroupWorkflowManager.RunWorkflow(Cart, OrderGroupWorkflowManager.CartCheckOutWorkflowName);
                }
                catch (Exception ex)
                {
                    if (ex is PaymentException)
                    {
                        throw ex;
                    }
                    else if (ex.InnerException != null && ex.InnerException is PaymentException)
                    {
                        throw ex.InnerException;
                    }
                }

                Cart.CustomerId = SecurityContext.Current.CurrentUserId;
                var po = Cart.SaveAsPurchaseOrder();

                if (_currentContact != null)
                {
                    _currentContact.LastOrder = po.Created;
                    _currentContact.SaveChanges();
                    Cart.CustomerName = _currentContact.FullName;
                }

                // Add note to purchaseOrder
                AddNoteToPurchaseOrder("New order placed by {0} in {1}", po, SecurityContext.Current.CurrentUserName, "Public site");
                po.AcceptChanges();

                PurchaseOrderManager.UpdatePromotionUsage(Cart, po);

                // Save latest order id
                Session[SessionLatestOrderIdKey]     = po.OrderGroupId;
                Session[SessionLatestOrderNumberKey] = po.TrackingNumber;
                Session[SessionLatestOrderTotalKey]  = new Money(po.Total, po.BillingCurrency).ToString();

                // Increase the coressponding KPI in CMO.
                IncreaseKpi();

                // Remove old cart
                Cart.Delete();
                Cart.AcceptChanges();

                // Commit changes
                scope.Complete();
            }
        }
Esempio n. 2
0
        // This method is about what we ended up with in "Fund." - with a few changes done for Adv.
        public ActionResult CheckOut(CheckOutViewModel model)
        {
            // SplitPay is in a Session-variable (bool)
            string paymentProcessResult = String.Empty;

            // Load the cart, it should be one there
            var cart = _orderRepository.Load <ICart>(GetContactId(), "Default").FirstOrDefault();

            if (cart == null)
            {
                throw new InvalidOperationException("No cart found"); // make nicer
            }

            #region What actually happens when loading a cart - Adv.

            //Cart cart = OrderContext.Current.GetCart(
            //    "SomeCart"
            //    , CustomerContext.Current.CurrentContactId
            //    , MarketId.Default); // ...is still what happens in behind

            #endregion

            // should clean-up among payments here if the  first time failed - Qty 10 test
            // quick fixdon in the base class

            // From Fund
            IOrderAddress theAddress = AddAddressToOrder(cart);

            // ToDo: Added this field for Adv. & Find ... doing it simple now using one Address
            // The address is for Find, but we need to add it to MDP to be able to use it properly
            // This is a Serialized cart, so doesn't crash if the field is not added to MDP
            theAddress.Properties["AddressType"] = "Shipping";

            #region Ship & Pay from Fund

            // ToDo: Define Shipping - From Fund
            AdjustFirstShipmentInOrder(cart, theAddress, model.SelectedShipId); // ...as a Shipment is added by epi

            // ToDo: Define Payment - From Fund
            AddPaymentToOrder(cart, model.SelectedPayId); // ...as this is not added by default

            #endregion

            #region Split Pay

            // RoCe: Fix this - addSecondPayment comes in as a param (bool)
            // ... force for now if BF-Card is found ... using Session
            if ((bool)Session["SecondPayment"] == true)
            {
                ccService.AddSecondPaymentToOrder(cart);
            }

            // gathered info
            this.frontEndMessage = ccService.FrontEndMessage;

            #endregion

            // Possible change of the cart... adding this
            // would have this done if a flag were set
            var cartReference = _orderRepository.Save(cart);

            // Original Fund... (with additions)
            IPurchaseOrder purchaseOrder;
            OrderReference orderReference;

            #region Transaction Scope

            using (var scope = new Mediachase.Data.Provider.TransactionScope()) // one in BF, also
            {
                var validationIssues = new Dictionary <ILineItem, ValidationIssue>();

                // Added - sets a lock on inventory...
                // ...could come earlier (outside tran) depending on TypeOf-"store"
                _inventoryProcessor.AdjustInventoryOrRemoveLineItem(cart.GetFirstShipment()
                                                                    , OrderStatus.InProgress, (item, issue) => validationIssues.Add(item, issue));

                if (validationIssues.Count >= 1)
                {
                    throw new Exception("Not possible right now"); // ...change approach
                }

                // just checking the cart in watch window
                var theShipping  = cart.GetFirstShipment();
                var theLineItems = cart.GetAllLineItems();
                var firstPayment = cart.GetFirstForm().Payments.First(); // no "GetFirstPayment()"
                var theforms     = cart.Forms;

                //_lineItemCalculator.GetDiscountedPrice()
                // second payment is added in the Trousers-Controller
                // ...fiddling with the GiftCarde as well

                // before 11
                //cart.ProcessPayments(_paymentProcessor, _orderGroupCalculator);

                // Gets the older one
                //IEnumerable<PaymentProcessingResult> theResult
                //    = cart.ProcessPayments(_paymentProcessor, _orderGroupCalculator);
                //paymentProcessResult = theResult.First().Message;

                PaymentProcessingResult otherResult =
                    _paymentProcessor.ProcessPayment(cart, cart.GetFirstForm().Payments.First(), cart.GetFirstShipment());

                frontEndMessage += otherResult.Message;

                if (otherResult.IsSuccessful)
                {
                    IPayment thePay = cart.GetFirstForm().Payments.First();
                    thePay.Status = PaymentStatus.Processed.ToString();
                }
                else
                {
                    IPayment thePay = cart.GetFirstForm().Payments.First();
                    thePay.Status = PaymentStatus.Failed.ToString();
                    throw new System.Exception("Bad payment"); // could have more grace
                }
                // A custom "shipping-processor" created (needs to do OldSchool-things right now)
                // Have a custom (very simple) Shipping-Provider added to the solution.
                // the processor can be cleaned up a lot, no need to show it

                // Custom thing... Error in 11... on currency... check later
                //ShippingProcessor p = new ShippingProcessor();
                //p.ProcessShipments(cart as OrderGroup); // have to go Old-school

                // ...only one form, still
                var totalProcessedAmount = cart.GetFirstForm().Payments.Where
                                               (x => x.Status.Equals(PaymentStatus.Processed.ToString())).Sum(x => x.Amount);

                // nice extension method
                var cartTotal = cart.GetTotal();

                // Do inventory - decrement or put back in stock
                if (totalProcessedAmount != cart.GetTotal(_orderGroupCalculator).Amount)
                {
                    // put back the reserved request
                    _inventoryProcessor.AdjustInventoryOrRemoveLineItem(cart.GetFirstShipment()
                                                                        , OrderStatus.Cancelled, (item, issue) => validationIssues.Add(item, issue));

                    #region OldSchool Inventory - no demo,just checking ... were undocumented and wrong in SDK
                    //List<InventoryRequestItem> requestItems = new List<InventoryRequestItem>(); // holds the "items"
                    //InventoryRequestItem requestItem = new InventoryRequestItem();

                    //// calls for some logic
                    //requestItem.RequestType = InventoryRequestType.Cancel; // as a demo
                    //requestItem.OperationKey = reqKey;

                    //requestItems.Add(requestItem);

                    //InventoryRequest inventoryRequest = new InventoryRequest(DateTime.UtcNow, requestItems, null);
                    //InventoryResponse inventoryResponse = _invService.Service.Request(inventoryRequest);

                    //InventoryRecord rec4 = _invService.Service.Get(LI.Code, wh.Code);
                    #endregion OldSchool

                    throw new InvalidOperationException("Wrong amount"); // maybe change approach
                }

                // RoCe: have to do Promos here also ... move stuff from cart to "base"

                // simulation... should be an "else"
                cart.GetFirstShipment().OrderShipmentStatus = OrderShipmentStatus.InventoryAssigned;
                // decrement inventory and let it go
                _inventoryProcessor.AdjustInventoryOrRemoveLineItem(cart.GetFirstShipment()
                                                                    , OrderStatus.Completed, (item, issue) => validationIssues.Add(item, issue));

                // Should do the ClubCard thing here - ClubMembers are logged in
                // PaymentMethodName = "GiftCard"
                if (CustomerContext.Current.CurrentContact != null)
                {
                    // check if GiftCard was used, don't give bonus for that payment
                    IEnumerable <IPayment> giftCardPayment = cart.GetFirstForm().Payments.Where
                                                                 (x => x.PaymentMethodName.Equals("GiftCard"));

                    if (giftCardPayment.Count() >= 1)
                    {
                        ccService.UpdateClubCard(cart, totalProcessedAmount - giftCardPayment.First().Amount);
                    }
                    else
                    {
                        // no GiftCard, but collecting points
                        ccService.UpdateClubCard(cart, totalProcessedAmount);
                    }
                }

                #region OldSchool Inventory check

                //List<InventoryRequestItem> requestItems1 = new List<InventoryRequestItem>(); // holds the "items"
                //InventoryRequestItem requestItem1 = new InventoryRequestItem();

                //// calls for some logic
                //requestItem1.RequestType = InventoryRequestType.Complete; // as a demo
                //requestItem1.OperationKey = reqKey;

                //requestItems1.Add(requestItem1);

                //InventoryRequest inventoryRequest1 = new InventoryRequest(DateTime.UtcNow, requestItems1, null);
                //InventoryResponse inventoryResponse1 = _invService.Service.Request(inventoryRequest1);

                //InventoryRecord rec3 = _invService.Service.Get(LI.Code, wh.Code); // inventory reserved, but not decremented

                #endregion OldSchool

                orderReference = _orderRepository.SaveAsPurchaseOrder(cart);
                _orderRepository.Delete(cart.OrderLink);

                //InventoryRecord rec5 = _invService.Service.Get(LI.Code, wh.Code); // just checking

                scope.Complete();
            } // End Tran

            #endregion

            #region JustChecking

            //Guid custLock;
            //OrderGroupLockManager.IsOrderGroupLocked(orderReference.OrderGroupId, out (Guid)CustomerContext.Current.CurrentContact.PrimaryKeyId));

            /*
             * OrderGroupLockManager.LockOrderGroup(orderReference.OrderGroupId
             *  , (Guid)CustomerContext.Current.CurrentContact.PrimaryKeyId);
             *
             * OrderGroupLockManager.UnlockOrderGroup(orderReference.OrderGroupId);
             */
            #endregion

            // just demoing (Find using this further down)
            purchaseOrder = _orderRepository.Load <IPurchaseOrder>(orderReference.OrderGroupId);

            // check the below
            var theType  = purchaseOrder.OrderLink.OrderType;
            var toString = purchaseOrder.OrderLink.ToString(); // Gets ID and Type ... combined

            #region ThisAndThat - from Fund

            // should do some with OrderStatusManager

            OrderStatus poStatus;
            poStatus = purchaseOrder.OrderStatus;
            //purchaseOrder.OrderStatus = OrderStatus.InProgress;

            //var info = OrderStatusManager.GetPurchaseOrderStatus(PO);

            var shipment = purchaseOrder.GetFirstShipment();
            var status   = shipment.OrderShipmentStatus;

            //shipment. ... no that much to do
            shipment.OrderShipmentStatus = OrderShipmentStatus.InventoryAssigned;

            #region Old-School, but some useful stuff

            //OrderStatusManager.ReleaseOrderShipment(purchaseOrder.GetFirstShipment() as Shipment);
            //OrderStatusManager.ReleaseOrderShipment(PO.OrderForms[0].Shipments[0]); // it gets released
            //OrderStatusManager.HoldOrder(PO); // it gets hold
            //OrderStatusManager.

            // seems to be a DTO involved... don't neeed to set the time like this... could use the new ordernote
            //OrderNotesManager.AddNoteToPurchaseOrder(PO, DateTime.UtcNow.ToShortDateString() + " done some for shipping", OrderNoteTypes.System, CustomerContext.Current.CurrentContactId);

            //            _orderRepository.Save(purchaseOrder); // check if it's like before ... yes it is needed to save again

            #endregion

            var notes = purchaseOrder.Notes; // IOrderNote is 0
            // RoCe - possible BUG
            // PO.OrderNotes works and contain the note above
            //IOrderNote theNewNote =
            Mediachase.Commerce.Orders.OrderNote otherNote = new OrderNote //IOrderNote
            {
                // Created = DateTime.Now, // do we need to set this ?? Nope .ctor does
                CustomerId = new Guid(), // can set this - regarded
                Detail     = "Order ToString(): " + toString + " - Shipment tracking number: " + shipment.ShipmentTrackingNumber,
                LineItemId = purchaseOrder.GetAllLineItems().First().LineItemId,
                // OrderGroupId = 12, R/O - error
                // OrderNoteId = 12, // can define it, but it's disregarded - no error
                Title = "Some title",
                Type  = OrderNoteTypes.Custom.ToString()
            };                                  // bug issued

            purchaseOrder.Notes.Add(otherNote); // void back
            purchaseOrder.ExpirationDate = DateTime.Now.AddMonths(1);


            PurchaseOrder oldPO = (PurchaseOrder)purchaseOrder;
            //oldPO.OrderAddresses.

            // yes, still need to come after adding notes
            _orderRepository.Save(purchaseOrder); // checking down here ... yes it needs to be saved again

            #endregion

            string conLang0 = ContentLanguage.PreferredCulture.Name;
            //string conLang1 = ContentLanguage.PreferredCulture.NativeName;
            //string conLang2 = ContentLanguage.PreferredCulture.TwoLetterISOLanguageName;

            // original shipment, could rewrite and get the dto so it can be used for the second shipment also
            // or grab the dto when loading into the dropdowns
            ShippingMethodDto.ShippingMethodRow theShip =
                ShippingManager.GetShippingMethod(model.SelectedShipId).ShippingMethod.First();

            #region Find & Queue plumbing

            // would be done async...
            if (IsOnLine) // just checking if the below is possible, if we have network access
            {
                // index PO and addresses for BoughtThisBoughtThat & demographic analysis
                IClient     client = Client.CreateFromConfig(); // native
                FindQueries Qs     = new FindQueries(client, true);
                Qs.OrderForFind(purchaseOrder);
            }

            if (poToQueue) // could have better tran-integrity, Extraction later in PO_Extract.sln/Sheduled job
            {
                // ToDo: Put a small portion of data from the PO to msmq, will eventually (out-of-process) go to the ERP
                string       QueueName = ".\\Private$\\MyQueue";
                MessageQueue Q1        = new MessageQueue(QueueName);
                MyMessage    m         = new MyMessage()
                {
                    poNr         = purchaseOrder.OrderNumber,
                    status       = purchaseOrder.OrderStatus.ToString(),
                    orderGroupId = orderReference.OrderGroupId
                };

                Q1.Send(m);
            }

            #endregion

            // Final steps, navigate to the order confirmation page
            StartPage        home = _contentLoader.Get <StartPage>(ContentReference.StartPage);
            ContentReference orderPageReference = home.Settings.orderPage;

            string passingValue = frontEndMessage + paymentProcessResult + " - " + purchaseOrder.OrderNumber;
            return(RedirectToAction("Index", new { node = orderPageReference, passedAlong = passingValue }));
        }
        //Exercise (E2) Do CheckOut
        public ActionResult CheckOut(CheckOutViewModel model)
        {
            // ToDo: declare a variable for CartHelper
            CartHelper ch = new CartHelper(Cart.DefaultName);

            int orderAddressId = 0;

            // ToDo: Addresses (an If-Else)
            if (CustomerContext.Current.CurrentContact == null)
            {
                // Anonymous... one way of "doing it"... for example, if no other address exist
                orderAddressId = ch.Cart.OrderAddresses.Add(
                    new OrderAddress
                {
                    CountryCode        = "SWE",
                    CountryName        = "Sweden",
                    Name               = "SomeCustomerAddress",
                    DaytimePhoneNumber = "123456",
                    FirstName          = "John",
                    LastName           = "Smith",
                    Email              = "*****@*****.**",
                });
            }
            else
            {
                // Logged in
                if (CustomerContext.Current.CurrentContact.PreferredShippingAddress == null)
                {
                    // no pref. address set... so we set one for the contact
                    CustomerAddress newCustAddress =
                        CustomerAddress.CreateForApplication(AppContext.Current.ApplicationId);
                    newCustAddress.AddressType        = CustomerAddressTypeEnum.Shipping; // mandatory
                    newCustAddress.ContactId          = CustomerContext.Current.CurrentContact.PrimaryKeyId;
                    newCustAddress.CountryCode        = "SWE";
                    newCustAddress.CountryName        = "Sweden";
                    newCustAddress.Name               = "new customer address"; // mandatory
                    newCustAddress.DaytimePhoneNumber = "123456";
                    newCustAddress.FirstName          = CustomerContext.Current.CurrentContact.FirstName;
                    newCustAddress.LastName           = CustomerContext.Current.CurrentContact.LastName;
                    newCustAddress.Email              = "*****@*****.**";

                    // note: Line1 & City is what is shown in CM at a few places... not the Name
                    CustomerContext.Current.CurrentContact.AddContactAddress(newCustAddress);
                    CustomerContext.Current.CurrentContact.SaveChanges();

                    // ... needs to be in this order
                    CustomerContext.Current.CurrentContact.PreferredShippingAddress = newCustAddress;
                    CustomerContext.Current.CurrentContact.SaveChanges(); // need this ...again

                    // then, for the cart
                    orderAddressId = ch.Cart.OrderAddresses.Add(new OrderAddress(newCustAddress));
                }
                else
                {
                    // there is a preferred address set (and, a fourth alternative exists... do later )
                    OrderAddress orderAddress =
                        new OrderAddress(CustomerContext.Current.CurrentContact.PreferredShippingAddress);

                    // then, for the cart
                    orderAddressId = ch.Cart.OrderAddresses.Add(orderAddress);
                }
            }

            // Depending how it was created...
            OrderAddress address = ch.FindAddressById(orderAddressId.ToString());

            // ToDo: Define Shipping
            ShippingMethodDto.ShippingMethodRow theShip =
                ShippingManager.GetShippingMethod(model.SelectedShipId).ShippingMethod.First();

            int shippingId = ch.Cart.OrderForms[0].Shipments.Add(
                new Shipment
            {                                          // ...removing anything?
                ShippingAddressId      = address.Name, // note: use no custom prefixes
                ShippingMethodId       = theShip.ShippingMethodId,
                ShippingMethodName     = theShip.Name,
                ShipmentTotal          = theShip.BasePrice,
                ShipmentTrackingNumber = "My tracking number",
            });

            // get the Shipping ... check to see if the Shipping knows about the LineItem
            Shipment firstOrderShipment = ch.Cart.OrderForms[0].Shipments.FirstOrDefault();

            // First (and only) OrderForm
            LineItemCollection lineItems = ch.Cart.OrderForms[0].LineItems;

            // ...basic now... one OrderForm - one Shipping
            foreach (LineItem lineItem in lineItems)
            {
                int index = lineItems.IndexOf(lineItem);
                if ((firstOrderShipment != null) && (index != -1))
                {
                    firstOrderShipment.AddLineItemIndex(index, lineItem.Quantity);
                }
            }


            // Execute the "Shipping & Taxes - WF" (CartPrepare) ... and take care of the return object
            WorkflowResults resultPrepare     = ch.Cart.RunWorkflow(OrderGroupWorkflowManager.CartPrepareWorkflowName);
            List <string>   wfMessagesPrepare = new List <string>(OrderGroupWorkflowManager.GetWarningsFromWorkflowResult(resultPrepare));


            // ToDo: Define Shipping
            PaymentMethodDto.PaymentMethodRow thePay = PaymentManager.GetPaymentMethod(model.SelectedPayId).PaymentMethod.First();
            Payment firstOrderPayment = ch.Cart.OrderForms[0].Payments.AddNew(typeof(OtherPayment));

            // ... need both below
            firstOrderPayment.Amount            = firstOrderShipment.SubTotal + firstOrderShipment.ShipmentTotal; // will change...
            firstOrderPayment.BillingAddressId  = address.Name;
            firstOrderPayment.PaymentMethodId   = thePay.PaymentMethodId;
            firstOrderPayment.PaymentMethodName = thePay.Name;
            // ch.Cart.CustomerName = "John Smith"; // ... this line overwrites what´s in there, if logged in


            // Execute the "Payment activation - WF" (CartCheckout) ... and take care of the return object
            // ...activates the gateway (same for shipping)
            WorkflowResults resultCheckout     = ch.Cart.RunWorkflow(OrderGroupWorkflowManager.CartCheckOutWorkflowName, false);
            List <string>   wfMessagesCheckout = new List <string>(OrderGroupWorkflowManager.GetWarningsFromWorkflowResult(resultCheckout));
            //ch.RunWorkflow("CartValidate") ... can see this (or variations)

            string        trackingNumber = String.Empty;
            PurchaseOrder purchaseOrder  = null;

            // Add a transaction scope and convert the cart to PO
            using (var scope = new Mediachase.Data.Provider.TransactionScope())
            {
                purchaseOrder = ch.Cart.SaveAsPurchaseOrder();
                ch.Cart.Delete();
                ch.Cart.AcceptChanges();
                trackingNumber = purchaseOrder.TrackingNumber;
                scope.Complete();
            }

            // Housekeeping below (Shipping release, OrderNotes and save the order)
            OrderStatusManager.ReleaseOrderShipment(purchaseOrder.OrderForms[0].Shipments[0]);

            OrderNotesManager.AddNoteToPurchaseOrder(purchaseOrder, DateTime.UtcNow.ToShortDateString() + " released for shipping", OrderNoteTypes.System, CustomerContext.Current.CurrentContactId);

            purchaseOrder.ExpirationDate = DateTime.UtcNow.AddDays(30);
            purchaseOrder.Status         = OrderStatus.InProgress.ToString();

            purchaseOrder.AcceptChanges(); // need this here, else no "order-note" persisted


            // Final steps, navigate to the order confirmation page
            StartPage        home = _contentLoader.Service.Get <StartPage>(ContentReference.StartPage);
            ContentReference orderPageReference = home.Settings.orderPage;

            string passingValue = trackingNumber;

            return(RedirectToAction("Index", new { node = orderPageReference, passedAlong = passingValue }));
        }
        // This method is about what we ended up with in "Fund." - with a few changes done for Adv.
        public ActionResult CheckOut(CheckOutViewModel model)
        {
            // SplitPay is in a Session-variable (bool)
            string paymentProcessResult = String.Empty;

            // Load the cart, it should be one there
            var cart = _orderRepository.Load <ICart>(GetContactId(), "Default").FirstOrDefault();

            if (cart == null)
            {
                throw new InvalidOperationException("No cart found"); // make nicer
            }

            // From Fund
            IOrderAddress theAddress = AddAddressToOrder(cart);

            // ToDo: Added this field for Adv. & Find ... doing it simple now using one Address
            // The address is for Find, but we need to add it to MDP to be able to use it properly
            // This is a Serialized cart, so doesn't crash if the field is not added to MDP
            theAddress.Properties["AddressType"] = "Shipping";

            #region Ship & Pay from Fund

            // ToDo: Define Shipping - From Fund
            AdjustFirstShipmentInOrder(cart, theAddress, model.SelectedShipId); // ...as a Shipment is added by epi

            // ToDo: Define Payment - From Fund
            AddPaymentToOrder(cart, model.SelectedPayId); // ...as this is not added by default

            #endregion

            #region Split Pay

            // RoCe: Fix this - addSecondPayment comes in as a param (bool)
            // ... force for now if BF-Card is found ... using Session
            if ((bool)Session["SecondPayment"] == true)
            {
                ccService.AddSecondPaymentToOrder(cart);
            }

            // gathered info
            this.frontEndMessage = ccService.FrontEndMessage;

            #endregion

            // Possible change of the cart... adding this
            // would have this done if a flag were set
            var cartReference = _orderRepository.Save(cart);

            // Original Fund... (with additions)
            IPurchaseOrder purchaseOrder;
            OrderReference orderReference;

            #region Transaction Scope

            using (var scope = new Mediachase.Data.Provider.TransactionScope()) // one in BF, also
            {
                var validationIssues = new Dictionary <ILineItem, ValidationIssue>();

                // Added - sets a lock on inventory...
                // ...could come earlier (outside tran) depending on TypeOf-"store"
                _inventoryProcessor.AdjustInventoryOrRemoveLineItem(cart.GetFirstShipment()
                                                                    , OrderStatus.InProgress, (item, issue) => validationIssues.Add(item, issue));

                if (validationIssues.Count >= 1)
                {
                    throw new Exception("Not possible right now"); // ...change approach
                }

                // just checking the cart in watch window
                var theShipping  = cart.GetFirstShipment();
                var theLineItems = cart.GetAllLineItems();
                var firstPayment = cart.GetFirstForm().Payments.First(); // no "GetFirstPayment()"
                var theforms     = cart.Forms;

                PaymentProcessingResult otherResult =
                    _paymentProcessor.ProcessPayment(cart, cart.GetFirstForm().Payments.First(), cart.GetFirstShipment());

                frontEndMessage += otherResult.Message;

                if (otherResult.IsSuccessful)
                {
                    IPayment thePay = cart.GetFirstForm().Payments.First();
                    thePay.Status = PaymentStatus.Processed.ToString();
                }
                else
                {
                    IPayment thePay = cart.GetFirstForm().Payments.First();
                    thePay.Status = PaymentStatus.Failed.ToString();
                    throw new System.Exception("Bad payment"); // could have more grace
                }

                // ...only one form, still
                var totalProcessedAmount = cart.GetFirstForm().Payments.Where
                                               (x => x.Status.Equals(PaymentStatus.Processed.ToString())).Sum(x => x.Amount);

                // nice extension method
                var cartTotal = cart.GetTotal();

                // Do inventory - decrement or put back in stock
                if (totalProcessedAmount != cart.GetTotal(_orderGroupCalculator).Amount)
                {
                    // put back the reserved request
                    _inventoryProcessor.AdjustInventoryOrRemoveLineItem(cart.GetFirstShipment()
                                                                        , OrderStatus.Cancelled, (item, issue) => validationIssues.Add(item, issue));

                    throw new InvalidOperationException("Wrong amount"); // maybe change approach
                }

                // RoCe: have to do Promos here also ... move stuff from cart to "base"
                // simulation... should be an "else"
                cart.GetFirstShipment().OrderShipmentStatus = OrderShipmentStatus.InventoryAssigned;

                // decrement inventory and let it go
                _inventoryProcessor.AdjustInventoryOrRemoveLineItem(cart.GetFirstShipment()
                                                                    , OrderStatus.Completed, (item, issue) => validationIssues.Add(item, issue));

                // Should do the ClubCard thing here - ClubMembers are logged in
                // PaymentMethodName = "GiftCard"
                if (CustomerContext.Current.CurrentContact != null)
                {
                    // check if GiftCard was used, don't give bonus for that payment
                    IEnumerable <IPayment> giftCardPayment = cart.GetFirstForm().Payments.Where
                                                                 (x => x.PaymentMethodName.Equals("GiftCard"));

                    if (giftCardPayment.Count() >= 1)
                    {
                        ccService.UpdateClubCard(cart, totalProcessedAmount - giftCardPayment.First().Amount);
                    }
                    else
                    {
                        // no GiftCard, but collecting points
                        ccService.UpdateClubCard(cart, totalProcessedAmount);
                    }
                }

                orderReference = _orderRepository.SaveAsPurchaseOrder(cart);
                _orderRepository.Delete(cart.OrderLink);

                scope.Complete();
            } // End Tran

            #endregion

            // just demoing (Find using this further down)
            purchaseOrder = _orderRepository.Load <IPurchaseOrder>(orderReference.OrderGroupId);

            // check the below
            var theType  = purchaseOrder.OrderLink.OrderType;
            var toString = purchaseOrder.OrderLink.ToString(); // Gets ID and Type ... combined

            #region ThisAndThat - from Fund

            OrderStatus poStatus;
            poStatus = purchaseOrder.OrderStatus;
            //purchaseOrder.OrderStatus = OrderStatus.InProgress;

            //var info = OrderStatusManager.GetPurchaseOrderStatus(PO);

            var shipment = purchaseOrder.GetFirstShipment();
            var status   = shipment.OrderShipmentStatus;

            //shipment. ... no that much to do
            shipment.OrderShipmentStatus = OrderShipmentStatus.InventoryAssigned;

            var notes = purchaseOrder.Notes; // IOrderNote is 0

            // have getters & setters... not good
            Mediachase.Commerce.Orders.OrderNote otherNote = new OrderNote //IOrderNote
            {
                // Created = DateTime.Now, // do we need to set this ?? Nope .ctor does
                CustomerId = new Guid(), // can set this - regarded
                Detail     = "Order ToString(): " + toString + " - Shipment tracking number: " + shipment.ShipmentTrackingNumber,
                LineItemId = purchaseOrder.GetAllLineItems().First().LineItemId,
                // OrderGroupId = 12, R/O - error
                // OrderNoteId = 12, // can define it, but it's disregarded - no error
                Title = "Some title",
                Type  = OrderNoteTypes.Custom.ToString()
            };                                  // bug issued

            purchaseOrder.Notes.Add(otherNote); // void back
            purchaseOrder.ExpirationDate = DateTime.Now.AddMonths(1);

            // yes, still need to come after adding notes
            _orderRepository.Save(purchaseOrder); // checking down here ... yes it needs to be saved again

            #endregion

            string conLang0 = ContentLanguage.PreferredCulture.Name;

            // original shipment, could rewrite and get the dto so it can be used for the second shipment also
            // or grab the dto when loading into the dropdowns
            ShippingMethodDto.ShippingMethodRow theShip =
                ShippingManager.GetShippingMethod(model.SelectedShipId).ShippingMethod.First();

            #region Find & Queue plumbing

            // would be done async...
            if (IsOnLine) // just checking if the below is possible, if we have network access
            {
                // index PO and addresses for BoughtThisBoughtThat & demographic analysis
                IClient     client = Client.CreateFromConfig(); // native
                FindQueries Qs     = new FindQueries(client, true);
                Qs.OrderForFind(purchaseOrder);
            }

            if (poToQueue) // could have better tran-integrity, Extraction later in PO_Extract.sln/Sheduled job
            {
                // ToDo: Put a small portion of data from the PO to msmq, will eventually (out-of-process) go to the ERP
                string       QueueName = ".\\Private$\\MyQueue";
                MessageQueue Q1        = new MessageQueue(QueueName);
                MyMessage    m         = new MyMessage()
                {
                    poNr         = purchaseOrder.OrderNumber,
                    status       = purchaseOrder.OrderStatus.ToString(),
                    orderGroupId = orderReference.OrderGroupId
                };

                Q1.Send(m);
            }

            #endregion

            // Final steps, navigate to the order confirmation page
            StartPage        home = _contentLoader.Get <StartPage>(ContentReference.StartPage);
            ContentReference orderPageReference = home.Settings.orderPage;

            string passingValue = frontEndMessage + paymentProcessResult + " - " + purchaseOrder.OrderNumber;
            return(RedirectToAction("Index", new { node = orderPageReference, passedAlong = passingValue }));
        }
        public ActionResult Buy(StartPage currentPage)
        {
            var cart   = LoadOrCreateCart();
            var market = _currentMarket.GetCurrentMarket();
            // Add shipping
            var shippingMethod = ShippingManager.GetShippingMethodsByMarket
                                     (market.MarketId.Value, false).ShippingMethod.FirstOrDefault();

            cart.OrderAddresses.Clear();
            cart.OrderForms.First().Shipments.Clear();
            cart.OrderForms.First().Payments.Clear();

            var shippingAddress = cart.OrderAddresses.AddNew();

            FillInAddress(shippingAddress);

            var shipment   = new Shipment();
            var shipmentId = cart.OrderForms.First().Shipments.Add(shipment);

            shipment.ShippingMethodId   = shippingMethod.ShippingMethodId;
            shipment.ShippingMethodName = shippingMethod.Name;
            shipment.SubTotal           = shippingMethod.BasePrice;

            // LineItem

            ContentReference theRef     = _refConv.GetContentLink("Long-Sleeve-Shirt-White-Small_1");
            VariationContent theContent = _contentLoader.Get <VariationContent>(theRef);
            LineItem         li         = CreateLineItem(theContent, 2, 22);

            var orderForm = cart.OrderForms.First();

            orderForm.LineItems.Add(li);
            var index = orderForm.LineItems.IndexOf(li);

            cart.OrderForms.First().Shipments.First().AddLineItemIndex(index, li.Quantity);


            //var liId = cart.OrderForms.First().LineItems.Add(li);
            //PurchaseOrderManager.AddLineItemToShipment(cart, 1, shipment, 2);

            // Add a pay method
            var paymentMethod = PaymentManager.GetPaymentMethodsByMarket(market.MarketId.Value)
                                .PaymentMethod.First();
            // Add Payment
            var payment = cart.OrderForms.First().Payments.AddNew(typeof(OtherPayment));

            payment.Amount            = 42; // ((IOrderGroup)cart).GetTotal(_totti).Amount;// .SubTotal.Amount;
            payment.PaymentMethodName = paymentMethod.Name;
            payment.PaymentMethodId   = paymentMethod.PaymentMethodId;
            payment.Status            = PaymentStatus.Pending.ToString();
            payment.TransactionID     = "transactionId";

            // No activations of Ship&Pay&Tax-providers in this example

            // Do the purchase
            using (var scope = new Mediachase.Data.Provider.TransactionScope())
            {
                OrderReference oRef = _orderRepository.SaveAsPurchaseOrder(cart);
                // I want to do this _orderRepository.Delete(cart);
                //_orderRepository.Delete(((IOrderGroup)cart).OrderLink);
                scope.Complete();
            }

            return(Content("Done"));
        }