Beispiel #1
0
        protected override DocumentInfo ComposeDocument(IUnitOfWork db,
                                                        long companyId,
                                                        MarketType market,
                                                        string marketplaceId,
                                                        IList <string> asinList)
        {
            var tag     = asinList != null && asinList.Count == 1 ? asinList[0] : null;
            var actions = _actionService.GetUnprocessedByType(db,
                                                              SystemActionType.UpdateOnMarketReturnOrder,
                                                              null,
                                                              tag);

            if (asinList != null)
            {
                actions = actions.Where(a => asinList.Contains(a.Tag)).ToList();
            }

            _actionOutputList = new Dictionary <long, ReturnOrderOutput>();

            if (actions.Any())
            {
                var orderMessages = new List <XmlElement>();
                var index         = 0;
                var merchant      = db.Companies.Get(companyId).AmazonFeedMerchantIdentifier;
                foreach (var action in actions)
                {
                    var data              = JsonConvert.DeserializeObject <ReturnOrderInput>(action.InputData);
                    var order             = db.Orders.GetByOrderNumber(data.OrderNumber);
                    var unsuitableData    = false;
                    var unsuitableMessage = "";
                    if (order == null)
                    {
                        unsuitableMessage = "Can't find orderId";
                        unsuitableData    = true;
                    }

                    if (data.Items == null)
                    {
                        unsuitableMessage = "No data items";
                        unsuitableData    = true;
                    }

                    if (data.Items != null && !data.Items.Any())
                    {
                        unsuitableMessage = "No return items";
                        unsuitableData    = true;
                    }

                    if (data.Items != null && !data.Items.Any(i => i.RefundShippingPrice > 0 || i.RefundItemPrice > 0))
                    {
                        unsuitableMessage = "All refund price = 0";
                        unsuitableData    = true;
                    }

                    if (unsuitableData)
                    {
                        Log.Info(marketplaceId + ": " + unsuitableMessage);
                        _actionService.SetResult(db, action.Id, SystemActionStatus.Suspended, new ReturnOrderOutput()
                        {
                            ResultMessage = unsuitableMessage
                        });
                        continue;
                    }

                    if (order.Market != (int)market ||
                        (!String.IsNullOrEmpty(marketplaceId) &&
                         order.MarketplaceId != marketplaceId))
                    {
                        //Log.Info("skip order=" + data.OrderNumber + ", market=" + order.Market + ", marketplace=" + order.MarketplaceId);
                        continue;
                    }

                    Log.Info(marketplaceId + ": add order " + index + ", actionId=" + action.Id + ", orderId=" + data.OrderNumber);

                    index++;

                    var returnItems = data.Items;
                    var orderItems  = db.OrderItems.GetAll().Where(oi => oi.OrderId == order.Id).ToList();
                    foreach (var returnItem in data.Items)
                    {
                        var existOrderItem = orderItems.FirstOrDefault(i => i.ItemOrderIdentifier == returnItem.ItemOrderId);
                        if (existOrderItem != null && returnItem.RefundItemPrice > 0 && existOrderItem.ItemPaid > 0 && existOrderItem.ItemTax > 0)
                        {
                            returnItem.RefundItemTax = (existOrderItem.ItemTax ?? 0) * returnItem.RefundItemPrice / (existOrderItem.ItemPaid.Value - existOrderItem.ItemTax.Value);
                        }
                    }

                    orderMessages.Add(FeedHelper.ComposeOrderAdjustmentMessage(index,
                                                                               data.OrderNumber,
                                                                               data.IncludeShipping,
                                                                               data.DeductShipping,
                                                                               data.IsDeductPrepaidLabelCost,
                                                                               order.TotalPriceCurrency,
                                                                               returnItems));

                    _actionOutputList.Add(new KeyValuePair <long, ReturnOrderOutput>(action.Id, new ReturnOrderOutput()
                    {
                        Identifier = index
                    }));
                }

                db.Commit(); //NOTE: Save SetResulte changes

                if (orderMessages.Any())
                {
                    Log.Info(marketplaceId + ": Compose feed");
                    var document = FeedHelper.ComposeFeed(orderMessages, merchant, Type.ToString());
                    return(new DocumentInfo
                    {
                        XmlDocument = document,
                        NodesCount = index
                    });
                }
            }
            return(null);
        }
        protected override DocumentInfo ComposeDocument(IUnitOfWork db, 
            long companyId, 
            MarketType market, 
            string marketplaceId,
            IList<string> asinList)
        {
            Log.Info("Get listings for price update");
            
            if (asinList == null || !asinList.Any())
            {
                Listings = db.Listings.GetPriceUpdateRequiredList(market, marketplaceId);
            }
            else
            {
                Listings = db.Listings.GetAll().Where(l => asinList.Contains(l.SKU)
                        && l.Market == (int)market
                        && (l.MarketplaceId == marketplaceId || String.IsNullOrEmpty(marketplaceId)))
                    .ToList();
            }


            if (Listings.Any())
            {
                var listingIdList = Listings.Select(l => l.Id).Distinct().ToList();
                var saleList = db.StyleItemSaleToListings.GetAllListingSaleAsDTO().Where(s => listingIdList.Contains(s.ListingId)).ToList();
                var itemIdList = Listings.Select(l => l.ItemId).Distinct().ToList();
                var items = db.Items.GetAll().Where(i => itemIdList.Contains(i.Id)).ToList();
                var styleItemIdList = items.Where(i => i.StyleItemId.HasValue).Select(i => i.StyleItemId).Distinct().ToList();
                var styleItems = db.StyleItems.GetAll().Where(si => styleItemIdList.Contains(si.Id)).ToList();

                var priceMessages = new List<XmlElement>();
                var index = 0;

                var priceToSend = new Dictionary<string, decimal>();

                foreach (var listing in Listings)
                {
                    if (priceToSend.ContainsKey(listing.SKU))
                        continue;

                    var existAutoPricing = false;
                    var item = items.FirstOrDefault(i => i.Id == listing.ItemId);
                    decimal? minAllowedPrice = null;
                    decimal? maxAllowedPrice = null;
                    if (item != null && item.StyleItemId.HasValue)
                    {
                        var styleItem = styleItems.FirstOrDefault(si => si.Id == item.StyleItemId.Value);
                        minAllowedPrice = styleItem.MinPrice;
                        maxAllowedPrice = styleItem.MaxPrice;
                        existAutoPricing = styleItem.MinPrice > 0 && styleItem.MaxPrice > 0;
                    }

                    index++;
                    Log.Info("add listing, index=" + index + ", listing=" + listing);

                    ViewListingSaleDTO sale = saleList.FirstOrDefault(s => s.ListingId == listing.Id);
                    if (sale != null)
                    {
                        sale.SaleStartDate = sale.SaleStartDate ?? sale.ListingSaleCreateDate;
                        sale.SaleEndDate = sale.SaleEndDate ?? Time.GetAppNowTime().Add(SaleManager.DefaultSalesPeriod);
                        Log.Info("sale: salePrice=" + sale.SalePrice
                                 + ", maxPiecesOnSale=" + sale.MaxPiecesOnSale
                                 + ", currentPiecesSaled=" + sale.PiecesSoldOnSale
                                 + ", saleStartDate=" + sale.SaleStartDate
                                 + ", saleEndDate=" + sale.SaleEndDate);
                    }

                    var now = Time.GetAppNowTime();
                    
                    var saleOn = sale != null 
                        && sale.SaleStartDate <= now
                        && (sale.SalePrice.HasValue || sale.SalePercent.HasValue);

                    var businessPrice = listing.AutoAdjustedPrice ?? listing.CurrentPrice;
                    var currentPrice = listing.AutoAdjustedPrice ?? listing.CurrentPrice;

                    decimal? salePrice = null;
                    if (sale != null && sale.SalePrice.HasValue)
                        salePrice = sale.SalePrice.Value;
                    if (sale != null && sale.SalePercent.HasValue)
                        salePrice = currentPrice - currentPrice * sale.SalePercent.Value/(decimal) 100;

                    if (saleOn)
                        businessPrice = salePrice.Value;
                    Log.Info("Current price=" + listing.CurrentPrice + ", Business price=" + businessPrice + ", Adjusted price=" + listing.AutoAdjustedPrice);

                    if (saleOn)
                    {
                        if (sale.SalePrice > currentPrice)
                        {
                            Log.Info("SalePrice > CurrentPrice, new currentPrice=" + currentPrice + " => " + salePrice + ", sale is OFF");

                            currentPrice = salePrice.Value;
                            saleOn = false;
                            sale = null;
                        }
                    }

                    priceMessages.Add(FeedHelper.ComposePriceMessage(index, 
                        listing.SKU, 
                        currentPrice,
                        businessPrice,
                        null,
                        sale != null ? salePrice : (decimal?)null,
                        sale != null ? sale.SaleStartDate : (DateTime?)null,
                        sale != null ? sale.SaleEndDate : (DateTime?)null,
                        minAllowedPrice,
                        maxAllowedPrice,
                        market,
                        marketplaceId));

                    listing.MessageIdentifier = index;

                    priceToSend.Add(listing.SKU, listing.CurrentPrice);
                }
                Log.Info("Compose feed");
                var merchant = db.Companies.Get(companyId).AmazonFeedMerchantIdentifier;
                var document = FeedHelper.ComposeFeed(priceMessages, merchant, Type.ToString());
                return new DocumentInfo
                {
                    XmlDocument = document,
                    NodesCount = index
                };
            }
            return null;
        }
Beispiel #3
0
        protected override DocumentInfo ComposeDocument(IUnitOfWork db,
                                                        long companyId,
                                                        MarketType market,
                                                        string marketplaceId,
                                                        IList <string> asinList)
        {
            //NOTE: reprocess cancel request every 2 hours
            var maxLastAttemptDate = Time.GetUtcTime().AddHours(-2);

            _cancelActions    = _actionService.GetUnprocessedByType(db, SystemActionType.UpdateOnMarketCancelOrder, maxLastAttemptDate, null);
            _actionOutputList = new Dictionary <long, CancelOrderOutput>();

            if (_cancelActions.Any())
            {
                var orderMessages = new List <XmlElement>();
                var index         = 0;
                var merchant      = db.Companies.Get(companyId).AmazonFeedMerchantIdentifier;
                foreach (var action in _cancelActions)
                {
                    var data  = JsonConvert.DeserializeObject <CancelOrderInput>(action.InputData);
                    var order = db.Orders.GetByOrderNumber(data.OrderNumber);
                    if (order == null)
                    {
                        Log.Info(marketplaceId + ": Can't find orderId=" + data.OrderNumber);
                        if (action.CreateDate < Time.GetAppNowTime().AddHours(-21)) //NOTE: Take care about 2 hours
                        {
                            var output = new CancelOrderOutput()
                            {
                                IsProcessed   = false,
                                ResultMessage = "Mark as cancelled w/o order by timeout"
                            };
                            _actionService.SetResult(db, action.Id, SystemActionStatus.Done, output);
                            db.Commit();

                            Log.Info("Mark as cancelled w/o order by timeout");
                        }
                        continue;
                    }

                    if (order.Market != (int)market ||
                        (!String.IsNullOrEmpty(marketplaceId) &&
                         order.MarketplaceId != marketplaceId))
                    {
                        //Log.Info("skip order=" + data.OrderNumber + ", market=" + order.Market + ", marketplace=" + order.MarketplaceId);
                        continue;
                    }

                    Log.Info(marketplaceId + ": add order " + index + ", actionId=" + action.Id + ", orderId=" + data.OrderNumber);

                    if (order.SourceOrderStatus == OrderStatusEnumEx.Canceled)
                    {
                        var output = new CancelOrderOutput()
                        {
                            IsProcessed   = false,
                            ResultMessage = "Already cancelled"
                        };
                        _actionService.SetResult(db, action.Id, SystemActionStatus.Done, output);
                        db.Commit();
                        continue;
                    }

                    index++;

                    var items = db.OrderItems.GetByOrderIdAsDto(data.OrderNumber)
                                //Remove canceled items with 0 price
                                .Where(m => m.ItemPrice > 0 || m.QuantityOrdered > 0).ToList();

                    OrderHelper.PrepareSourceItemOrderId(items);
                    items = OrderHelper.GroupBySourceItemOrderId(items);

                    orderMessages.Add(FeedHelper.ComposeOrderAcknowledgementMessage(index,
                                                                                    data.OrderNumber,
                                                                                    items));

                    _actionOutputList.Add(new KeyValuePair <long, CancelOrderOutput>(action.Id, new CancelOrderOutput()
                    {
                        Identifier = index
                    }));
                }

                if (orderMessages.Any())
                {
                    Log.Info(marketplaceId + ": Compose feed");
                    var document = FeedHelper.ComposeFeed(orderMessages, merchant, Type.ToString());
                    return(new DocumentInfo
                    {
                        XmlDocument = document,
                        NodesCount = index
                    });
                }
            }
            return(null);
        }
        protected override DocumentInfo ComposeDocument(IUnitOfWork db,
                                                        long companyId,
                                                        MarketType market,
                                                        string marketplaceId,
                                                        IList <string> asinList)
        {
            Dictionary <string, int> _quantityToSend = new Dictionary <string, int>();

            Log.Info("Get listings for quantity update");
            var requestInfoes = db.SystemActions.GetAllAsDto()
                                .Where(a => a.Type == (int)SystemActionType.UpdateOnMarketProductQuantity &&
                                       a.Status != (int)SystemActionStatus.Done)
                                .ToList();

            var requestedSKUs = requestInfoes.Select(i => i.Tag).ToList();
            var dtoItems      = (from i in db.Items.GetAllViewAsDto()
                                 where requestedSKUs.Contains(i.SKU) &&
                                 i.PublishedStatus == (int)PublishedStatuses.Published &&
                                 i.Market == (int)market &&
                                 (String.IsNullOrEmpty(marketplaceId) || i.MarketplaceId == marketplaceId)
                                 select i).ToList();

            foreach (var dtoItem in dtoItems)
            {
                var requestInfo = requestInfoes.FirstOrDefault(i => i.Tag == dtoItem.SKU);
                var info        = SystemActionHelper.FromStr <UpdateQtyInput>(requestInfo.InputData);
                dtoItem.Id           = (int)(requestInfo?.Id ?? 0);
                dtoItem.RealQuantity = info.NewQty;
            }

            _quantityToSend = new Dictionary <string, int>();

            if (dtoItems.Any())
            {
                var quantMessages = new List <XmlElement>();
                var index         = 0;

                foreach (var listing in dtoItems)
                {
                    //Skip processing duplicate SKU
                    if (_quantityToSend.ContainsKey(listing.SKU))
                    {
                        continue;
                    }

                    index++;
                    var quantity = listing.RealQuantity;

                    Log.Info("add listing " + index
                             + ", listingId=" + listing.Id
                             + ", SKU=" + listing.SKU
                             + ", quantity=" + quantity);

                    quantMessages.Add(FeedHelper.ComposeInventoryMessage(index,
                                                                         listing.SKU,
                                                                         quantity,
                                                                         null,
                                                                         _fulfillmentLatency));

                    _quantityToSend.Add(listing.SKU, quantity);
                }
                Log.Info("Compose feed");
                var merchant = db.Companies.Get(companyId).AmazonFeedMerchantIdentifier;
                var document = FeedHelper.ComposeFeed(quantMessages, merchant, Type.ToString());
                return(new DocumentInfo
                {
                    XmlDocument = document,
                    NodesCount = index
                });
            }
            return(null);
        }
        protected override DocumentInfo ComposeDocument(IUnitOfWork db,
                                                        long companyId,
                                                        MarketType market,
                                                        string marketplaceId,
                                                        IList <string> asinList)
        {
            Log.Info("Get listings for quantity update");
            if (asinList == null || !asinList.Any())
            {
                Listings = db.Listings.GetQuantityUpdateRequiredList(market, marketplaceId);
            }
            else
            {
                Listings = db.Listings.GetAll().Where(l => asinList.Contains(l.SKU) &&
                                                      l.Market == (int)market &&
                                                      (l.MarketplaceId == marketplaceId || String.IsNullOrEmpty(marketplaceId)))
                           .ToList();
            }


            _quantityToSend = new Dictionary <string, int>();

            if (Listings.Any())
            {
                var quantMessages = new List <XmlElement>();
                var index         = 0;

                foreach (var listing in Listings)
                {
                    //Skip processing duplicate SKU
                    if (_quantityToSend.ContainsKey(listing.SKU))
                    {
                        continue;
                    }

                    index++;
                    //NOTE: Case when we have 2 duplicate listings with different styleId (in case when manufacturer change StyleId)
                    var realQuantity = Listings.Where(l => l.SKU == listing.SKU).Sum(l => l.RealQuantity);

                    var quantity = listing.DisplayQuantity.HasValue ?
                                   Math.Min(listing.DisplayQuantity.Value, realQuantity)
                        : listing.RealQuantity;

                    //NOTE: 101 qty rule
                    if (quantity >= 30)
                    {
                        quantity = 101;
                    }

                    Log.Info("add listing " + index
                             + ", listingId=" + listing.Id
                             + ", SKU=" + listing.SKU
                             + ", quantity=" + quantity
                             + " (display=" + listing.DisplayQuantity + ", real=" + realQuantity + "(" + listing.RealQuantity + ")" + ")" +
                             " , restockDate=" + listing.RestockDate);

                    quantMessages.Add(FeedHelper.ComposeInventoryMessage(index, listing.SKU, quantity, listing.RestockDate, _fulfillmentLatency));
                    listing.MessageIdentifier = index;

                    _quantityToSend.Add(listing.SKU, quantity);
                }
                Log.Info("Compose feed");
                var merchant = db.Companies.Get(companyId).AmazonFeedMerchantIdentifier;
                var document = FeedHelper.ComposeFeed(quantMessages, merchant, Type.ToString());
                return(new DocumentInfo
                {
                    XmlDocument = document,
                    NodesCount = index
                });
            }
            return(null);
        }
Beispiel #6
0
        protected override DocumentInfo ComposeDocument(IUnitOfWork db,
                                                        long companyId,
                                                        MarketType market,
                                                        string marketplaceId,
                                                        IList <string> asinList)
        {
            Log.Info("Get orders");
            var shippingMethodList = db.ShippingMethods.GetAllAsDto().ToList();
            var fromDate           = Time.GetAppNowTime().AddDays(-7);

            var shippingLabels = db.OrderShippingInfos.GetOrdersToFulfillAsDTO(market, marketplaceId)
                                 .Where(sh => sh.ShippingDate > fromDate).ToList();
            var shippingInfoIds = shippingLabels.Select(i => i.Id).ToList();

            Shippings      = db.OrderShippingInfos.GetFiltered(sh => shippingInfoIds.Contains(sh.Id)).ToList();
            shippingLabels = PrepareOrderShippings(db, shippingLabels);

            var mailLabels = db.MailLabelInfos.GetInfosToFulfillAsDTO(market, marketplaceId)
                             .Where(sh => sh.ShippingDate > fromDate).ToList();
            var mailInfoIds = mailLabels.Select(i => i.Id).ToList();

            MailInfoes = db.MailLabelInfos.GetFiltered(m => mailInfoIds.Contains(m.Id)).ToList();
            mailLabels = PrepareMailShippings(db, mailLabels);

            var allShippings = shippingLabels;

            allShippings.AddRange(mailLabels);

            if (asinList != null)
            {
                allShippings = allShippings.Where(sh => asinList.Contains(sh.AmazonIdentifier)).ToList();
            }

            if (allShippings.Any())
            {
                var orderMessages = new List <XmlElement>();
                var index         = 0;
                var merchant      = db.Companies.Get(companyId).AmazonFeedMerchantIdentifier;
                foreach (var shipping in allShippings)
                {
                    index++;
                    Log.Info("add order " + index + ", shippingId=" + shipping.Id);

                    var shippingMethod = shippingMethodList.FirstOrDefault(m => m.Id == shipping.ShippingMethodId);

                    string shippingService = String.Empty;
                    if (string.IsNullOrEmpty(shipping.ShippingService)) //NOTE: this options using Mail Labels, todo: make join
                    {
                        if (shippingMethod != null)
                        {
                            shippingService = shippingMethod.Name;
                        }
                        Log.Info("shipping service=" + shippingService);
                    }
                    else
                    {
                        shippingService = shipping.ShippingService;
                    }

                    OrderHelper.PrepareSourceItemOrderId(shipping.Items);
                    shipping.Items = OrderHelper.GroupBySourceItemOrderId(shipping.Items);

                    var carrier = shippingMethod?.CarrierName;
                    if (!String.IsNullOrEmpty(shipping.CustomCurrier))
                    {
                        carrier = shipping.CustomCurrier;
                    }

                    orderMessages.Add(FeedHelper.ComposeOrderFulfillmentMessage(index,
                                                                                shipping.AmazonIdentifier,
                                                                                shipping.ShippingDate,
                                                                                shipping.OrderDate,
                                                                                ShippingUtils.FormattedToMarketShippingService(shippingService, shippingMethod.IsInternational),
                                                                                shippingMethod != null ? ShippingUtils.FormattedToMarketCurrierName(carrier, shippingMethod.IsInternational, market) : String.Empty,
                                                                                shipping.TrackingNumber,
                                                                                shipping.Items));

                    if (shipping.IsFromMailPage)
                    {
                        MailInfoes.First(m => m.Id == shipping.Id).MessageIdentifier = index;
                    }
                    else
                    {
                        Shippings.First(o => o.Id == shipping.Id).MessageIdentifier = index;
                    }
                }
                Log.Info("Compose feed");
                var document = FeedHelper.ComposeFeed(orderMessages, merchant, Type.ToString());
                return(new DocumentInfo
                {
                    XmlDocument = document,
                    NodesCount = index
                });
            }
            return(null);
        }