using BBWY.Common.Http; using BBWY.Common.Models; using BBWY.Server.Model; using BBWY.Server.Model.Dto; using Microsoft.Extensions.Options; using NLog; using System.Threading.Tasks; using Yitter.IdGenerator; using System.Linq; using BBWY.Server.Model.Db; using System; using System.Collections.Generic; using Newtonsoft.Json; using FreeSql; using System.Threading; using System.Collections.Concurrent; namespace BBWY.Server.Business.Sync { public class ProductSyncBusiness : BaseSyncBusiness, IDenpendency { private ProductBusiness productBusiness; private ConcurrentDictionary categoryCache; public ProductSyncBusiness(RestApiService restApiService, IOptions options, NLogManager nLogManager, IFreeSql fsql, IIdGenerator idGenerator, TaskSchedulerManager taskSchedulerManager, VenderBusiness venderBusiness, ProductBusiness productBusiness, YunDingBusiness yunDingBusiness) : base(restApiService, options, nLogManager, fsql, idGenerator, taskSchedulerManager, venderBusiness, yunDingBusiness) { this.productBusiness = productBusiness; this.categoryCache = new ConcurrentDictionary(); } private void SyncProduct(ShopResponse shop, bool IsSyncAllProduct = false) { try { var shopId = long.Parse(shop.ShopId); var dbProductList = fsql.Select().Where(p => p.ShopId == shopId).ToList(); var dbProductSkuList = fsql.Select().Where(p => p.ShopId == shopId).ToList(); List productList = new List(); List productSkuList = new List(); List insertProductList = new List(); List insertProductSkuList = new List(); List> updateProductList = new List>(); List> updateProductSkuList = new List>(); var request = new SearchProductRequest() { PageSize = 50, PageIndex = 1, AppKey = shop.AppKey, AppSecret = shop.AppSecret, AppToken = shop.AppToken, Platform = shop.PlatformId }; while (true) { var currentProductList = productBusiness.GetProductList(request); if (currentProductList == null || currentProductList.Count == 0) break; productList.AddRange(currentProductList.Items); foreach (var product in currentProductList.Items) { var currentSkuList = productBusiness.GetProductSkuList(new SearchProductSkuRequest() { AppKey = shop.AppKey, AppSecret = shop.AppSecret, AppToken = shop.AppToken, Platform = shop.PlatformId, Spu = product.Id, IsContainSource = true }); if (currentSkuList == null || currentSkuList.Count() == 0) continue; productSkuList.AddRange(currentSkuList); } if (currentProductList.Items.Count < 50 || !IsSyncAllProduct) break; request.PageIndex++; Thread.Sleep(1000); } #region 找出新增的产品 var newProductList = productList.Where(p => !dbProductList.Any(dp => dp.Id == p.Id)).ToList(); if (newProductList.Count() > 0) { insertProductList.AddRange(newProductList.Select(p => new Product() { Id = p.Id, CreateTime = p.CreateTime, Title = p.Title, State = p.State, ShopId = shopId, Platform = shop.PlatformId, ProductItemNum = p.ProductItemNum, MainSkuId = productSkuList.FirstOrDefault(s => s.ProductId == p.Id)?.Id })); } #endregion #region 找出变化的产品 (状态,标题) var stateChangeProductList = productList.Where(p => dbProductList.Any(dp => dp.Id == p.Id && (dp.State != p.State || dp.Title != p.Title))).ToList(); if (stateChangeProductList.Count() > 0) { foreach (var product in stateChangeProductList) { var update = fsql.Update(product.Id).Set(p => p.State, product.State) .Set(p => p.Title, product.Title); updateProductList.Add(update); } } #endregion #region 找出接口查不出的产品 var goneProductList = dbProductList.Where(dp => !productList.Any(p => p.Id == dp.Id)).ToList(); if (goneProductList.Count() > 0) { var goneProductIdList = goneProductList.Select(p => p.Id).ToList(); var update = fsql.Update().Set(p => p.State, -1).Where(p => goneProductIdList.Contains(p.Id)); updateProductList.Add(update); } #endregion #region 找出新增的SKU var newProductSkuList = productSkuList.Where(p => !dbProductSkuList.Any(dp => dp.Id == p.Id)).ToList(); if (newProductSkuList.Count() > 0) { insertProductSkuList.AddRange(newProductSkuList.Select(p => new ProductSku() { Id = p.Id, CreateTime = p.CreateTime, Title = p.Title, State = p.State, ShopId = shopId, Platform = shop.PlatformId, Logo = p.Logo, ProductId = p.ProductId, Price = p.Price, CategoryId = p.Source.Value("categoryId"), CategoryName = GetCategoryName(shop, p.Source.Value("categoryId")) })); } #endregion #region 找出状态变化的SKU var stateChangeProductSkuList = productSkuList.Where(p => dbProductSkuList.Any(dp => dp.Id == p.Id && (dp.State != p.State || dp.Title != p.Title || dp.Price != p.Price || dp.Logo != p.Logo))).ToList(); if (stateChangeProductSkuList.Count() > 0) { foreach (var productSku in stateChangeProductSkuList) { var update = fsql.Update(productSku.Id).Set(p => p.State, productSku.State) .Set(p => p.Title, productSku.Title) .Set(p => p.Price, productSku.Price) .Set(p => p.Logo, productSku.Logo); updateProductSkuList.Add(update); } } #endregion #region 找出缺少类目的sku var noCategoryProductList = productSkuList.Where(p => dbProductSkuList.Any(dp => dp.Id == p.Id && string.IsNullOrEmpty(dp.CategoryName))).ToList(); if (noCategoryProductList.Count() > 0) { foreach (var productSku in noCategoryProductList) { var categoryName = GetCategoryName(shop, productSku.Source.Value("categoryId")); var update = fsql.Update(productSku.Id).Set(p => p.CategoryName, categoryName); updateProductSkuList.Add(update); } } #endregion #region 找出接口查不出的SKU var goneProductSkuList = dbProductSkuList.Where(dp => !productSkuList.Any(p => p.Id == dp.Id)).ToList(); if (goneProductSkuList.Count() > 0) { var goneProductSkuIdList = goneProductSkuList.Select(p => p.Id).ToList(); var update = fsql.Update().Set(p => p.State, 4).Where(p => goneProductSkuIdList.Contains(p.Id)); updateProductSkuList.Add(update); } #endregion fsql.Transaction(() => { if (insertProductList.Count() > 0) fsql.Insert(insertProductList).ExecuteAffrows(); if (insertProductSkuList.Count() > 0) fsql.Insert(insertProductSkuList).ExecuteAffrows(); if (updateProductList.Count() > 0) { foreach (var update in updateProductList) update.ExecuteAffrows(); } if (updateProductSkuList.Count() > 0) { foreach (var update in updateProductSkuList) update.ExecuteAffrows(); } }); } catch (Exception ex) { var shopData = JsonConvert.SerializeObject(shop); nLogManager.Default().Error(ex, $"SyncProduct ShopData:{shopData}"); } } /// /// 同步所有店铺的前50个产品 /// public void SyncAllShopProduct() { var shopList = venderBusiness.GetShopList(platform: Enums.Platform.京东); //SyncProduct(shopList.FirstOrDefault(s => s.ShopId == "12657364"), true); //布莱特玩具专营店 foreach (var shop in shopList) { Task.Factory.StartNew(() => SyncProduct(shop), System.Threading.CancellationToken.None, TaskCreationOptions.LongRunning, taskSchedulerManager.ProductSyncTaskScheduler); } } /// /// 同步所有店铺的全部产品 /// public void SyncAllShopAllProduct() { var shopList = venderBusiness.GetShopList(platform: Enums.Platform.京东); //SyncProduct(shopList.FirstOrDefault(s => s.ShopName == "披风熊玩具专营店"), true); foreach (var shop in shopList) { Task.Factory.StartNew(() => SyncProduct(shop, true), CancellationToken.None, TaskCreationOptions.LongRunning, taskSchedulerManager.ProductSyncTaskScheduler); } } private string GetCategoryName(ShopResponse shop, string categoryId) { if (categoryCache.TryGetValue(categoryId, out string name)) return name; try { var res = productBusiness.GetCategoyrInfo(new JDQueryCategoryRequest() { AppKey = shop.AppKey, CategoryId = categoryId, AppSecret = shop.AppSecret, AppToken = shop.AppToken, Platform = shop.PlatformId }); categoryCache.TryAdd(categoryId, res.Name); name = res.Name; } catch { } return name; } } }