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; }
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); }
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); }