public override void SetUp()
            {
                base.SetUp();

                _orderModel = Fixture.Create<PurchaseOrderModel>();
                _currentUser = new Mock<IIdentity>().Object;
            }
        public DeliveryReceipt(ICurrentMarket currentMarket, PurchaseOrderModel purchaseOrder)
        {
            if (purchaseOrder == null) throw new ArgumentNullException("purchaseOrder cannot be null");

            _purchaseOrder = purchaseOrder;
            _orderViewModel = new OrderViewModel(currentMarket.GetCurrentMarket().DefaultCurrency.Format, _purchaseOrder);

            To = _orderViewModel.Email;

            var localizationService = ServiceLocator.Current.GetInstance<LocalizationService>();
            IMarketService marketService = ServiceLocator.Current.GetInstance<IMarketService>();
            IMarket market = GetMarketForOrder(purchaseOrder, marketService, currentMarket);

            string emailSubject = localizationService.GetStringByCulture("/common/receipt/email/subject", market.DefaultLanguage);

            Subject = string.Format(emailSubject, _purchaseOrder.TrackingNumber);
            BackendOrderNumber = _orderViewModel.ErpOrderNumber;
            PurchaseOrderNumber = _purchaseOrder.TrackingNumber;

            // Get first shipment tracking number
            if (_purchaseOrder.OrderForms != null &&
                _purchaseOrder.OrderForms.Any() &&
                _purchaseOrder.OrderForms.First().Shipments != null &&
                _purchaseOrder.OrderForms.First().Shipments.Any())
            {
                TrackingNumber = _purchaseOrder.OrderForms.First().Shipments.First().ShipmentTrackingNumber;
            }
        }
        public void AdjustStocks(PurchaseOrderModel order)
        {
            // TODO: Verify if you need custom inventory adjustment
            // The workflows will adjust the inventory for us, as long as inventory tracking
            // is enabled on the variation and the warehouse inventory for this variation. If you
            // want to refresh the inventory from a back-end system, do it here.

            // AdjustOrderInventoryFromWarehouse(order);
        }
        public void ProcessCompletedPayment(PurchaseOrderModel orderModel, IIdentity identity)
        {
            _orderService.FinalizeOrder(orderModel.TrackingNumber, identity);

            SendAndLogOrderReceipt(orderModel);

            AttemptStockAdjustment(orderModel);

            ForwardOrderToErp(orderModel);
        }
        public OrderViewModel(IFormatProvider currencyFormat, PurchaseOrderModel order)
            : this(currencyFormat)
        {
            OrderNumber = order.TrackingNumber;
            OrderDate   = order.Created;
            Status      = order.Status;

            TotalLineItemsAmount = order.OrderForms.First().LineItems.Sum(i => i.ExtendedPrice);
            TotalAmount          = order.Total;
            Shipping             = order.ShippingTotal;

            // TODO: Make taxes work as it should, instead of flat hard codet 25% tax
            if (order.TaxTotal == 0 && order.Total > 0)
            {
                order.TaxTotal = ((decimal)0.25) * order.Total;
            }
            Tax = order.TaxTotal;


            Discount = order.OrderForms.First().LineItems.Sum(i => i.LineItemDiscountAmount + i.OrderLevelDiscountAmount) + order.OrderForms.First().Shipments.First().ShippingDiscountAmount;
            if (order.OrderForms.Any() && order.OrderForms.First().Payments.Any())
            {
                PaymentMethod = order.OrderForms.First().Payments.First().PaymentMethodName;
            }

            Email          = order.BillingEmail;
            Phone          = order.BillingPhone;
            BillingAddress = new Address(order.OrderAddresses.FirstOrDefault(a => a.Name == Constants.Order.BillingAddressName));
            var shippingAddress = order.OrderAddresses.FirstOrDefault(a => a.Name == Constants.Order.ShippingAddressName);
            ShippingAddress  = new Address(shippingAddress);
            DeliveryLocation = "";
            if (shippingAddress != null && !string.IsNullOrWhiteSpace(shippingAddress.DeliveryServicePoint))
            {
                DeliveryLocation = shippingAddress.DeliveryServicePoint;
            }

            foreach (var item in order.OrderForms.First().LineItems)
            {
                OrderLines.Add(new OrderLineViewModel(item));
            }

            // discounts
            var discounts = CartService.GetAllDiscounts(order);
            DiscountCodes = discounts.Where(x => !string.IsNullOrEmpty(x.DiscountCode)).Select(x => x.DiscountCode).ToList();

            ShippingTrackingNumber = "";
            if (order.OrderForms.Any() &&
                order.OrderForms.First().Shipments != null &&
                order.OrderForms.First().Shipments.Any())
            {
                ShippingTrackingNumber = order.OrderForms.First().Shipments.First().ShipmentTrackingNumber;
            }

            ErpOrderNumber = order.BackendOrderNumber;
        }
        public OrderViewModel(IFormatProvider currencyFormat, PurchaseOrderModel order)
            : this(currencyFormat)
        {
            OrderNumber = order.TrackingNumber;
            OrderDate = order.Created;
            Status = order.Status;

            TotalLineItemsAmount = order.OrderForms.First().LineItems.Sum(i => i.ExtendedPrice);
            TotalAmount = order.Total;
            Shipping = order.ShippingTotal;

            // TODO: Make taxes work as it should, instead of flat hard codet 25% tax
            if (order.TaxTotal == 0 && order.Total > 0)
            {
                order.TaxTotal = ((decimal)0.25) * order.Total;
            }
            Tax = order.TaxTotal;

            Discount = order.OrderForms.First().LineItems.Sum(i => i.LineItemDiscountAmount + i.OrderLevelDiscountAmount) + order.OrderForms.First().Shipments.First().ShippingDiscountAmount;
            if (order.OrderForms.Any() && order.OrderForms.First().Payments.Any())
            {
                PaymentMethod = order.OrderForms.First().Payments.First().PaymentMethodName;
            }

            Email = order.BillingEmail;
            Phone = order.BillingPhone;
            BillingAddress = new Address(order.OrderAddresses.FirstOrDefault(a => a.Name == Constants.Order.BillingAddressName));
            var shippingAddress = order.OrderAddresses.FirstOrDefault(a => a.Name == Constants.Order.ShippingAddressName);
            ShippingAddress = new Address(shippingAddress);
            DeliveryLocation = "";
            if (shippingAddress != null && !string.IsNullOrWhiteSpace(shippingAddress.DeliveryServicePoint))
                DeliveryLocation = shippingAddress.DeliveryServicePoint;

            foreach (var item in order.OrderForms.First().LineItems)
            {
                OrderLines.Add(new OrderLineViewModel(item));
            }

            // discounts
            var discounts = CartService.GetAllDiscounts(order);
            DiscountCodes = discounts.Where(x => !string.IsNullOrEmpty(x.DiscountCode)).Select(x => x.DiscountCode).ToList();

            ShippingTrackingNumber = "";
            if (order.OrderForms.Any() &&
                order.OrderForms.First().Shipments != null &&
                order.OrderForms.First().Shipments.Any())
            {
                ShippingTrackingNumber = order.OrderForms.First().Shipments.First().ShipmentTrackingNumber;
            }

            ErpOrderNumber = order.BackendOrderNumber;
        }
 private void AttemptStockAdjustment(PurchaseOrderModel orderModel)
 {
     try
     {
         // Not extremely important that this succeeds.
         // Stocks are continually adjusted from ERP.
         _stockUpdater.AdjustStocks(orderModel);
     }
     catch (Exception e)
     {
         Log.Error("Error adjusting inventory after purchase.", e);
     }
 }
        protected void AdjustOrderInventoryFromWarehouse(PurchaseOrderModel order)
        {
            var warehouseRepository = ServiceLocator.Current.GetInstance<IWarehouseRepository>();
            var warehousesCache = warehouseRepository.List();
            var warehouseInventory = ServiceLocator.Current.GetInstance<IWarehouseInventoryService>();

            var expirationCandidates = new HashSet<ProductContent>();

            var referenceConverter = ServiceLocator.Current.GetInstance<ReferenceConverter>();
            var contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();

            // Adjust inventory
            foreach (var f in order.OrderForms)
            {
                foreach (var i in f.LineItems)
                {
                    try
                    {
                        var warehouse = warehousesCache.First(w => w.Code == i.WarehouseCode);
                        var catalogEntry = CatalogContext.Current.GetCatalogEntry((string) i.CatalogEntryId);
                        var catalogKey = new CatalogKey(catalogEntry);
                        var inventory = new WarehouseInventory(warehouseInventory.Get(catalogKey, warehouse));

                        inventory.InStockQuantity = inventory.InStockQuantity - i.Quantity;
                        if (inventory.InStockQuantity <= 0)
                        {
                            var contentLink = referenceConverter.GetContentLink(i.CatalogEntryId);
                            var variant = contentRepository.Get<VariationContent>(contentLink);

                            expirationCandidates.Add((ProductContent) variant.GetParent());
                        }

                        // NOTE! Default implementation is to NOT save the inventory here,
                        // as it will subtract double if the workflows also do this.
                        // warehouseInventory.Save(inventory);
                    }
                    catch (Exception ex)
                    {
                        Log.Error("Unable to adjust inventory.", ex);
                    }
                }
            }

            // TODO: Determine if you want to unpublish products with no sellable variants
            ExpireProductsWithNoInventory(expirationCandidates, contentRepository);
            // Alterntive approach is to notify the commerce admin about the products without inventory
        }
        public void AdjustStocks(PurchaseOrderModel order)
        {
            var warehouseRepository = ServiceLocator.Current.GetInstance<IWarehouseRepository>();
            var warehousesCache = warehouseRepository.List();
            var warehouseInventory = ServiceLocator.Current.GetInstance<IWarehouseInventoryService>();

            var expirationCandidates = new HashSet<ProductContent>();

            var referenceConverter = ServiceLocator.Current.GetInstance<ReferenceConverter>();
            var contentRepository = ServiceLocator.Current.GetInstance<IContentRepository>();

            // Adjust inventory
            foreach (var f in order.OrderForms)
            {
                foreach (var i in f.LineItems)
                {
                    try
                    {
                        var warehouse = warehousesCache.First(w => w.Code == i.WarehouseCode);
                        var catalogEntry = CatalogContext.Current.GetCatalogEntry(i.CatalogEntryId);
                        var catalogKey = new CatalogKey(catalogEntry);
                        var inventory = new WarehouseInventory(warehouseInventory.Get(catalogKey, warehouse));

                        if ((inventory.InStockQuantity -= i.Quantity) <= 0)
                        {
                            var contentLink = referenceConverter.GetContentLink(i.CatalogEntryId);
                            var variant = contentRepository.Get<VariationContent>(contentLink);

                            expirationCandidates.Add((ProductContent)variant.GetParent());
                        }

                        warehouseInventory.Save(inventory);
                    }
                    catch (Exception ex)
                    {
                        LoggerExtensions.Error((ILogger) Log, "Unable to adjust inventory.", ex);
                    }

                }
            }

            // TODO: Determine if you want to unpublish products with no sellable variants
            // ExpireProductsWithNoInventory(expirationCandidates, contentRepository);
            // Alterntive approach is to notify the commerce admin about the products without inventory
        }
        public Receipt(IMarket market, PurchaseOrderModel purchaseOrder)
        {
            if (market == null)
                throw new ArgumentNullException("market");

            if (purchaseOrder == null)
                throw new ArgumentNullException("purchaseOrder");

            _purchaseOrder = purchaseOrder;

            _orderViewModel = new OrderViewModel(market.DefaultCurrency.Format, purchaseOrder);

            To = _orderViewModel.Email;

            var localizationService = ServiceLocator.Current.GetInstance<LocalizationService>();

            Subject = string.Format(localizationService.GetString("/common/receipt/email/subject"), _purchaseOrder.TrackingNumber);
        }
        public bool SendDeliveryReceipt(PurchaseOrderModel order, string language = null)
        {
            var mailSettings = _notificationSettingsRepository.GetNotificationSettings(language);
            if (mailSettings != null)
            {
                var emailMessage = new DeliveryReceipt(_currentMarket, order);
                emailMessage.From = mailSettings.From;
                emailMessage.Header = mailSettings.MailHeader.ToString();
                emailMessage.Footer = mailSettings.MailFooter.ToString();

                var result = _emailDispatcher.SendEmail(emailMessage);
                if (result.Success)
                {
                    return true;
                }
                else
                {
                    Log.Error(result.Exception.Message, result.Exception);
                    return false;
                }
            }
            Log.Error("Unable to get notification settings");
            return false;
        }
 protected IMarket GetMarketForOrder(PurchaseOrderModel purchaseOrder, IMarketService marketService, ICurrentMarket currentMarket)
 {
     if (purchaseOrder.MarketId != null && purchaseOrder.MarketId.Value != null)
     {
         return marketService.GetMarket(purchaseOrder.MarketId);
     }
     return currentMarket.GetCurrentMarket();
 }
 public bool SendOrderReceipt(PurchaseOrderModel orderModel)
 {
     IEmailService emailService = EPiServer.ServiceLocation.ServiceLocator.Current.GetInstance<IEmailService>();
     if(orderModel == null)
         throw new ArgumentNullException("orderModel");
     return emailService.SendOrderReceipt(orderModel);
 }
        public bool SendOrderReceipt(PurchaseOrderModel order)
        {
            var mailSettings = _notificationSettingsRepository.GetNotificationSettings();
            if (mailSettings != null)
            {
                IMarket market = _marketService.GetMarket(order.MarketId);
                var emailMessage = new Receipt(market, order);
                if (string.IsNullOrEmpty(mailSettings.From))
                    throw new ArgumentException("Missing From address in email settings");

                emailMessage.From = mailSettings.From;
                emailMessage.Header = mailSettings.MailHeader.ToString();
                emailMessage.Footer = mailSettings.MailFooter.ToString();

                if (string.IsNullOrEmpty(emailMessage.To))
                    throw new ArgumentException("Missing To address");

                var result = _emailDispatcher.SendEmail(emailMessage);
                if (result.Success)
                {
                    return true;
                }
                else
                {
                    Log.Error(result.Exception.Message, result.Exception);
                    return false;
                }
            }
            Log.Error("Unable to get notification settings");
            return false;
        }
 public DibsPaymentProcessingResult(PurchaseOrderModel order, string message)
 {
     _message = message;
     _order = order;
 }
        public static List<DiscountModel> GetAllDiscounts(PurchaseOrderModel order)
        {
            var discounts = new List<DiscountModel>();
            foreach (var form in order.OrderForms)
            {
                foreach (var discount in form.Discounts.Where(x => !String.IsNullOrEmpty(x.DiscountCode)))
                {
                    AddToDiscountList(discount, discounts);
                }

                foreach (var item in form.LineItems)
                {
                    foreach (var discount in item.Discounts.Where(x => !String.IsNullOrEmpty(x.DiscountCode)))
                    {
                        AddToDiscountList(discount, discounts);
                    }
                }

                foreach (var shipment in form.Shipments)
                {
                    foreach (var discount in shipment.Discounts.Where(x => !String.IsNullOrEmpty(x.DiscountCode)))
                    {
                        AddToDiscountList(discount, discounts);
                    }
                }
            }
            return discounts;
        }
 public void ForwardOrderToErp(PurchaseOrderModel purchaseOrder)
 {
     // TODO: Implement for your solution
 }
 private void SendAndLogOrderReceipt(PurchaseOrderModel orderModel)
 {
     var sendOrderReceiptResult = SendOrderReceipt(orderModel);
     Log.Debug("Sending receipt e-mail - " + (sendOrderReceiptResult ? "success" : "failed"));
 }
 private bool SendOrderReceipt(PurchaseOrderModel order)
 {
     return _emailService.SendOrderReceipt(order);
 }