public bool IsValid(IUnitOfWork db,
                            out IList <MessageString> messages)
        {
            messages = new List <MessageString>();

            if (Id == null || Id == 0)
            {
                //Check ASIN
                var existParent = db.ParentItems.GetByASIN(ASIN, (MarketType)Market, MarketplaceId);
                if (existParent != null)
                {
                    messages.Add(new MessageString()
                    {
                        Status  = MessageStatus.Error,
                        Message = "Specified Parent ASIN already exists in the current marketplace"
                    });
                    return(false);
                }
            }

            //Check SKU
            var skuList = VariationList
                          .Where(v => !String.IsNullOrEmpty(v.SKU) && v.IsSelected)
                          .Select(v => v.SKU)
                          .ToList();

            var notSelectedItemIds = VariationList.Where(v => !v.IsSelected && v.Id.HasValue).Select(v => v.Id).ToList();

            var existSKUs = db.Listings.GetAll().Where(l => !l.IsRemoved &&
                                                       skuList.Contains(l.SKU) &&
                                                       !notSelectedItemIds.Contains(l.ItemId) &&
                                                       l.Market == Market &&
                                                       l.MarketplaceId == MarketplaceId).ToList();

            foreach (var item in VariationList.Where(v => v.IsSelected))
            {
                if (!String.IsNullOrEmpty(item.SKU))
                {
                    var existItemSKU = existSKUs.Where(s => s.ItemId != item.Id && s.SKU == item.SKU).Take(1).ToList();

                    var skuMessages = new List <MessageString>();
                    existItemSKU.ForEach(s => skuMessages.Add(new MessageString()
                    {
                        Status  = MessageStatus.Error,
                        Message = String.Format("The variation SKU: \"{0}\" already exists in current marketplace", s.SKU)
                    }));
                    messages.AddRange(skuMessages);
                }
            }

            //Check Barcode
            CheckBarcodes(db, (MarketType)Market, MarketplaceId, VariationList, messages, false, false);
            CheckBarcodes(db, (MarketType)Market, MarketplaceId, VariationList, messages, true, false);
            CheckBarcodes(db, (MarketType)Market, MarketplaceId, VariationList, messages, false, true);

            return(!messages.Any());
        }
        public string Export(IUnitOfWork db,
                             ITime time,
                             ILogService log,
                             IBarcodeService barcodeService,
                             IMarketCategoryService categoryService,
                             IMarketplaceService marketplaceService,
                             DateTime when,
                             long?by)
        {
            log.Info("Export, parentId=" + Id + ", market=" + Market + ", marketplaceId=" + MarketplaceId);

            string filename    = null;
            var    parent      = db.ParentItems.GetAsDTO((int)Id);
            var    parentImage = db.ParentItemImages.GetAllAsDto().FirstOrDefault(pi => pi.ItemId == parent.Id);

            parent.LargeImage = parentImage;

            var parentChildren = db.Items.GetAllActualExAsDto().Where(i => i.ParentASIN == parent.ASIN && //NOTE: use original ASIN
                                                                      i.Market == (int)parent.Market &&
                                                                      i.MarketplaceId == parent.MarketplaceId).ToList();

            //if (exportMode != ExportToExcelMode.FBA) //TASK: Generate excel only for listing that haven't FBA
            parentChildren = parentChildren.Where(i => !i.IsFBA).ToList();
            parentChildren = parentChildren
                             .OrderBy(ch => ch.StyleString)
                             .ThenBy(ch => SizeHelper.GetSizeIndex(ch.Size))
                             .ToList();

            var children = VariationList
                           .Where(v => v.IsSelected &&
                                  !String.IsNullOrEmpty(v.StyleString))
                           .Select(v => new ItemExDTO()
            {
                StyleString  = v.StyleString,
                StyleId      = v.StyleId,
                StyleItemId  = v.StyleItemId,
                Barcode      = v.Barcode,
                SKU          = v.SKU,
                Size         = v.Size,
                Color        = v.Color,
                CurrentPrice = v.Price,
            }).ToList();

            parent.ASIN       = ASIN;
            parent.AmazonName = Name;

            var styleStringList = children.Select(ch => ch.StyleString).Distinct().ToList();
            var styles          = db.Styles.GetAllActive().Where(s => styleStringList.Contains(s.StyleID)).ToList();

            for (int i = 0; i < children.Count; i++)
            {
                var style = styles.FirstOrDefault(s => s.StyleID == children[i].StyleString);
                if (style != null)
                {
                    children[i].StyleId = style.Id;
                }

                var existParentChild = parentChildren.FirstOrDefault(p => String.Compare(p.SKU, children[i].SKU, StringComparison.OrdinalIgnoreCase) == 0);
                if (existParentChild != null)
                {
                    children[i].Id   = existParentChild.Id;
                    children[i].ASIN = existParentChild.ASIN;

                    children[i].Name            = existParentChild.Name;
                    children[i].ImageUrl        = existParentChild.ImageUrl;
                    children[i].IsExistOnAmazon = existParentChild.IsExistOnAmazon;

                    children[i].ListPrice   = existParentChild.ListPrice;
                    children[i].BrandName   = existParentChild.BrandName;
                    children[i].SpecialSize = existParentChild.SpecialSize;
                    children[i].Features    = existParentChild.Features;
                    children[i].Department  = existParentChild.Department;

                    children[i].RealQuantity = existParentChild.RealQuantity;
                    children[i].Weight       = existParentChild.Weight; //NOTE: only for FBA
                    children[i].IsPrime      = existParentChild.IsPrime;
                }
            }

            var resultRecords = ExcelProductUSViewModel.GetItemsFor(db,
                                                                    categoryService,
                                                                    ExportToExcelMode.Normal,
                                                                    null,
                                                                    parent,
                                                                    children,
                                                                    PictureSourceType == PictureSourceTypes.FromStyle ? UseStyleImageModes.StyleImage : UseStyleImageModes.ListingImage,
                                                                    out filename);

            //NOTE: mark already exist listings as PartialUpdate
            foreach (var resultRecord in resultRecords)
            {
                if (resultRecord.Id > 0 &&
                    resultRecord.Parentage == ExcelHelper.ParentageChild &&
                    resultRecord.IsExistOnAmazon)
                {
                    resultRecord.Update        = "PartialUpdate";
                    resultRecord.Quantity      = null;
                    resultRecord.StandardPrice = null;
                    //resultRecord.SuggestedPrice = null;
                    //resultRecord.MainImageURL = null;
                    //resultRecord.OtherImageUrl1 = null;
                    //resultRecord.OtherImageUrl2 = null;
                    //resultRecord.OtherImageUrl3 = null;
                }
            }

            var firstResult = resultRecords.FirstOrDefault(r => r.Parentage == ExcelHelper.ParentageChild);

            if (firstResult != null)
            {
                foreach (var resultRecord in resultRecords)
                {
                    if (CopyBulletPoints &&
                        resultRecord.Id == 0 &&
                        resultRecord.Parentage == ExcelHelper.ParentageChild)
                    {
                        resultRecord.KeyProductFeatures1 = firstResult.KeyProductFeatures1;
                        resultRecord.KeyProductFeatures2 = firstResult.KeyProductFeatures2;
                        resultRecord.KeyProductFeatures3 = firstResult.KeyProductFeatures3;
                        resultRecord.KeyProductFeatures4 = firstResult.KeyProductFeatures4;
                        resultRecord.KeyProductFeatures5 = firstResult.KeyProductFeatures5;

                        resultRecord.SearchTerms1 = firstResult.SearchTerms1;
                    }
                }
            }

            var styleStringToGenerate = children.Where(ch => ch.Id == 0).Select(ch => ch.StyleString).Distinct().ToList();

            foreach (var styleString in styleStringToGenerate)
            {
                var styleDto   = db.Styles.GetActiveByStyleIdAsDto(styleString);
                var styleModel = new StyleViewModel(db, marketplaceService, styleDto);
                //Update Barcode and AutoGenerateBarcode flag, other info already exists in resultRecords
                foreach (var si in styleModel.StyleItems.Items)
                {
                    var variationItem = VariationList.FirstOrDefault(v => v.StyleItemId == si.Id);
                    if (variationItem != null)
                    {
                        if (!String.IsNullOrEmpty(variationItem.Barcode))
                        {
                            si.Barcodes = new[] { new BarcodeDTO()
                                                  {
                                                      Barcode = variationItem.Barcode
                                                  } }
                        }
                        ;
                        si.AutoGeneratedBarcode = variationItem.AutoGeneratedBarcode;
                    }
                }

                string tempFilename       = null;
                var    styleResultRecords = ExcelProductUSViewModel.GenerateToExcelUS(db, barcodeService, categoryService, styleModel, when, out tempFilename);

                foreach (var styleResultRecord in styleResultRecords)
                {
                    if (!styleResultRecord.StyleItemId.HasValue)
                    {
                        continue;
                    }

                    var resultRecord = resultRecords.FirstOrDefault(s => s.StyleItemId == styleResultRecord.StyleItemId);
                    if (resultRecord != null)
                    {
                        resultRecord.ASIN      = styleResultRecord.ASIN;
                        resultRecord.ProductId = styleResultRecord.ProductId;

                        resultRecord.Title          = styleResultRecord.Title;
                        resultRecord.Description    = styleResultRecord.Description;
                        resultRecord.BrandName      = styleResultRecord.BrandName;
                        resultRecord.Type           = styleResultRecord.Type;
                        resultRecord.MainImageURL   = styleResultRecord.MainImageURL;
                        resultRecord.OtherImageUrl1 = styleResultRecord.OtherImageUrl1;
                        resultRecord.OtherImageUrl2 = styleResultRecord.OtherImageUrl2;
                        resultRecord.OtherImageUrl3 = styleResultRecord.OtherImageUrl3;
                        resultRecord.Department     = styleResultRecord.Department;

                        resultRecord.SuggestedPrice = styleResultRecord.SuggestedPrice;
                        resultRecord.Quantity       = styleResultRecord.Quantity;

                        if (!CopyBulletPoints)
                        {
                            resultRecord.KeyProductFeatures1 = styleResultRecord.KeyProductFeatures1;
                            resultRecord.KeyProductFeatures2 = styleResultRecord.KeyProductFeatures2;
                            resultRecord.KeyProductFeatures3 = styleResultRecord.KeyProductFeatures3;
                            resultRecord.KeyProductFeatures4 = styleResultRecord.KeyProductFeatures4;
                            resultRecord.KeyProductFeatures5 = styleResultRecord.KeyProductFeatures5;

                            resultRecord.SearchTerms1 = styleResultRecord.SearchTerms1;
                        }
                    }
                }
            }


            var stream = ExcelHelper.ExportIntoFile(HttpContext.Current.Server.MapPath(ExcelProductUSViewModel.USTemplatePath),
                                                    "Template",
                                                    resultRecords);

            var filePath = UrlHelper.GetProductTemplateFilePath(filename);

            using (var file = File.Open(filePath, FileMode.Create))
            {
                stream.WriteTo(file);
            }
            return(UrlHelper.GetProductTemplateUrl(filename));
        }
    }