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)
        {
            Log.Info("Get listings for price rule update");

            var             toDate = Time.GetAppNowTime().AddHours(-30);
            IList <ItemDTO> dtoItems;


            if (asinList == null || !asinList.Any())
            {
                var requestInfoes = db.SystemActions.GetAllAsDto()
                                    .Where(a => a.Type == (int)SystemActionType.UpdateOnMarketProductPriceRule &&
                                           a.Status != (int)SystemActionStatus.Done)
                                    .ToList();

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

                foreach (var dtoItem in dtoItems)
                {
                    var requestInfo = requestInfoes.FirstOrDefault(i => i.Tag == dtoItem.SKU);
                    dtoItem.Id = (int)(requestInfo?.Id ?? 0);
                }
            }
            else
            {
                dtoItems = db.Items.GetAllViewAsDto()
                           .Where(i => i.Market == (int)market &&
                                  (String.IsNullOrEmpty(marketplaceId) || i.MarketplaceId == marketplaceId) &&
                                  i.StyleItemId.HasValue &&
                                  i.StyleId.HasValue &&
                                  asinList.Contains(i.SKU))
                           .ToList();
                dtoItems.ForEach(i => i.Id = 0);
            }

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

                var priceLines = new List <PriceRuleLine>();
                var index      = 0;

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

                foreach (var dtoItem in dtoItems)
                {
                    if (!dtoItem.StyleItemId.HasValue)
                    {
                        continue;
                    }

                    var listing   = listings.FirstOrDefault(l => l.Id == dtoItem.ListingEntityId);
                    var styleItem = styleItems.FirstOrDefault(si => si.Id == dtoItem.StyleItemId.Value);

                    if (styleItem == null)
                    {
                        continue;
                    }

                    if (priceToSend.ContainsKey(listing.SKU))
                    {
                        continue;
                    }

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

                    var ruleName   = "M004";
                    var ruleAction = styleItem.MinPrice.HasValue && styleItem.MaxPrice.HasValue ? "START" : "STOP"; //STOP
                    var minPrice   = styleItem.MinPrice ?? 0;
                    var maxPrice   = styleItem.MaxPrice ?? 0;

                    priceLines.Add(new PriceRuleLine()
                    {
                        Id         = dtoItem.Id,
                        SKU        = listing.SKU,
                        MinPrice   = minPrice,
                        MaxPrice   = maxPrice,
                        RuleName   = ruleName,
                        RuleAction = ruleAction
                    });

                    //listing.MessageIdentifier = index;

                    priceToSend.Add(listing.SKU, listing.CurrentPrice);
                }
                Log.Info("Compose feed");
                //var merchant = db.Companies.Get(companyId).AmazonFeedMerchantIdentifier;
                var document = ComposeFeed(priceLines);


                return(new DocumentInfo
                {
                    TextDocument = document,
                    NodesCount = index,
                    FeedItems = priceLines.Select(i => new FeedItemDTO()
                    {
                        MessageId = 0,
                        ItemId = i.Id,
                    }).ToList()
                });
            }
            return(null);
        }