diff --git a/BBWY.Server.API/Controllers/ProductSyncController.cs b/BBWY.Server.API/Controllers/ProductSyncController.cs new file mode 100644 index 00000000..7b9c2f17 --- /dev/null +++ b/BBWY.Server.API/Controllers/ProductSyncController.cs @@ -0,0 +1,25 @@ +using BBWY.Server.Business.Sync; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; + +namespace BBWY.Server.API.Controllers +{ + + public class ProductSyncController : BaseApiController + { + private ProductSyncBusiness productSyncBusiness; + public ProductSyncController(IHttpContextAccessor httpContextAccessor, ProductSyncBusiness productSyncBusiness) : base(httpContextAccessor) + { + this.productSyncBusiness = productSyncBusiness; + } + + /// + /// 全店同步产品 + /// + [HttpPost] + public void SyncAllShopProduct() + { + productSyncBusiness.SyncAllShopProduct(); + } + } +} diff --git a/BBWY.Server.Business/Sync/ProductSyncBusiness.cs b/BBWY.Server.Business/Sync/ProductSyncBusiness.cs new file mode 100644 index 00000000..711eaf61 --- /dev/null +++ b/BBWY.Server.Business/Sync/ProductSyncBusiness.cs @@ -0,0 +1,124 @@ +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; + +namespace BBWY.Server.Business.Sync +{ + public class ProductSyncBusiness : BaseSyncBusiness, IDenpendency + { + private ProductBusiness productBusiness; + + public ProductSyncBusiness(RestApiService restApiService, + IOptions options, + ILogger logger, + IFreeSql fsql, + IIdGenerator idGenerator, + TaskSchedulerManager taskSchedulerManager, + VenderBusiness venderBusiness, + ProductBusiness productBusiness) : base(restApiService, + options, + logger, + fsql, + idGenerator, + taskSchedulerManager, + venderBusiness) + { + this.productBusiness = productBusiness; + } + + private void SyncProduct(ShopResponse shop) + { + try + { + var shopId = long.Parse(shop.ShopId); + var productList = productBusiness.GetProductList(new SearchProductRequest() + { + PageSize = 50, + PageIndex = 1, + AppKey = shop.AppKey, + AppSecret = shop.AppSecret, + AppToken = shop.AppToken, + Platform = shop.PlatformId + }); + + if (productList == null || productList.Count == 0) + return; + + var productIds = productList.Items.Select(p => p.Id); + + var dbProductIds = fsql.Select().Where(p => p.ShopId == shopId && p.Platform == shop.PlatformId && productIds.Contains(p.Id)).ToList(p => p.Id); + var noExtisProductIds = productIds.Except(dbProductIds).ToList(); + if (noExtisProductIds.Count() == 0) + return; + + var insertProductList = productList.Items.Where(p => noExtisProductIds.Contains(p.Id)).Select(p => new Product() + { + Id = p.Id, + CreateTime = DateTime.Now, + Platform = shop.PlatformId, + ProductItemNum = p.ProductItemNum, + ShopId = shopId, + Title = p.Title + }).ToList(); + + var inserSkuList = new List(); + foreach (var product in insertProductList) + { + var skuList = productBusiness.GetProductSkuList(new SearchProductSkuRequest() + { + AppKey = shop.AppKey, + AppSecret = shop.AppSecret, + AppToken = shop.AppToken, + Platform = shop.PlatformId, + Spu = product.Id + }); + inserSkuList.AddRange(skuList.Select(s => new ProductSku() + { + Id = s.Id, + CreateTime = DateTime.Now, + Logo = s.Logo, + Platform = shop.PlatformId, + Price = s.Price, + ProductId = s.ProductId, + ShopId = shopId, + Title = s.Title + })); + } + + fsql.Transaction(() => + { + fsql.Insert(insertProductList).ExecuteAffrows(); + fsql.Insert(inserSkuList).ExecuteAffrows(); + }); + } + catch (Exception ex) + { + var shopData = JsonConvert.SerializeObject(shop); + logger.Error(ex, $"SyncProduct ShopData:{shopData}"); + } + } + + /// + /// 同步所有店铺的订单 + /// + public void SyncAllShopProduct() + { + var shopList = venderBusiness.GetShopList(); + foreach (var shop in shopList) + { + Task.Factory.StartNew(() => SyncProduct(shop), System.Threading.CancellationToken.None, TaskCreationOptions.LongRunning, taskSchedulerManager.ProductSyncTaskScheduler); + } + } + } +} + diff --git a/BBWY.Server.Business/TaskSchedulerManager.cs b/BBWY.Server.Business/TaskSchedulerManager.cs index 764b17e6..7e966818 100644 --- a/BBWY.Server.Business/TaskSchedulerManager.cs +++ b/BBWY.Server.Business/TaskSchedulerManager.cs @@ -6,6 +6,8 @@ namespace BBWY.Server.Business { public LimitedConcurrencyLevelTaskScheduler SyncOrderTaskScheduler { get; private set; } + public LimitedConcurrencyLevelTaskScheduler ProductSyncTaskScheduler { get; private set; } + public LimitedConcurrencyLevelTaskScheduler SyncRefundOrderTaskScheduler { get; private set; } public LimitedConcurrencyLevelTaskScheduler SyncAfterOrderTaskScheduler { get; private set; } @@ -18,6 +20,7 @@ namespace BBWY.Server.Business SyncRefundOrderTaskScheduler = new LimitedConcurrencyLevelTaskScheduler(10); SyncAfterOrderTaskScheduler = new LimitedConcurrencyLevelTaskScheduler(10); PurchaseOrderCallbackTaskScheduler = new LimitedConcurrencyLevelTaskScheduler(10); + ProductSyncTaskScheduler = new LimitedConcurrencyLevelTaskScheduler(5); } } } diff --git a/BBWY.Server.Model/Db/Product/Product.cs b/BBWY.Server.Model/Db/Product/Product.cs new file mode 100644 index 00000000..c20b4913 --- /dev/null +++ b/BBWY.Server.Model/Db/Product/Product.cs @@ -0,0 +1,39 @@ +using FreeSql.DataAnnotations; +using System; + +namespace BBWY.Server.Model.Db +{ + + [Table(Name = "product", DisableSyncStructure = true)] + public partial class Product { + + /// + /// SPU + /// + [Column(StringLength = 50, IsPrimary = true, IsNullable = false)] + public string Id { get; set; } + + [Column(DbType = "datetime")] + public DateTime? CreateTime { get; set; } + + [Column(DbType = "int(1)", MapType = typeof(int))] + public Enums.Platform Platform { get; set; } + + /// + /// 货号 + /// + [Column(StringLength = 100)] + public string ProductItemNum { get; set; } + + + public long? ShopId { get; set; } + + /// + /// 标题 + /// + + public string Title { get; set; } + + } + +} diff --git a/BBWY.Server.Model/Db/Product/ProductSku.cs b/BBWY.Server.Model/Db/Product/ProductSku.cs new file mode 100644 index 00000000..1fb50e41 --- /dev/null +++ b/BBWY.Server.Model/Db/Product/ProductSku.cs @@ -0,0 +1,46 @@ +using FreeSql.DataAnnotations; +using System; + +namespace BBWY.Server.Model.Db +{ + + [Table(Name = "productsku", DisableSyncStructure = true)] + public partial class ProductSku + { + + /// + /// SKU + /// + [Column(StringLength = 50, IsPrimary = true, IsNullable = false)] + public string Id { get; set; } + + [Column(DbType = "datetime")] + public DateTime? CreateTime { get; set; } + + + public string Logo { get; set; } + + [Column(DbType = "int(1)", MapType = typeof(int))] + public Enums.Platform Platform { get; set; } + + /// + /// 售价 + /// + [Column(DbType = "decimal(18,2)")] + public decimal? Price { get; set; } + + /// + /// SPU + /// + [Column(StringLength = 50)] + public string ProductId { get; set; } + + + public long? ShopId { get; set; } + + + public string Title { get; set; } + + } + +}