Browse Source

批量修改拳探采购方案归属采购商

AddValidOverTime
shanji 2 years ago
parent
commit
63ab22f016
  1. 12
      BBWY.Common/Extensions/CopyExtensions.cs
  2. 11
      BBWY.Server.API/Controllers/PurchaseSchemeController.cs
  3. 295
      BBWY.Server.Business/PurchaseScheme/PurchaseProductAPIService.cs
  4. 109
      BBWY.Server.Business/PurchaseScheme/PurchaseSchemeBusiness.cs
  5. 10
      BBWY.Server.Model/Dto/Request/PurchaseScheme/BatchUpdateQTPurchaseSchemeBelongPurchaserRequest.cs
  6. 42
      BBWY.Server.Model/Dto/Request/PurchaseScheme/PurcasheSkuBasicInfoRequest.cs
  7. 58
      BBWY.Server.Model/Dto/Response/PurchaseScheme/PurchaseProductBasicInfoResponse.cs
  8. 9
      BBWY.Server.Model/Enums.cs

12
BBWY.Common/Extensions/CopyExtensions.cs

@ -0,0 +1,12 @@
using Newtonsoft.Json;
namespace BBWY.Common.Extensions
{
public static class CopyExtensions
{
public static T Copy<T>(this T p)
{
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(p));
}
}
}

11
BBWY.Server.API/Controllers/PurchaseSchemeController.cs

@ -70,5 +70,16 @@ namespace BBWY.Server.API.Controllers
{
return purchaseSchemeBusiness.GetSharePurchaser(querySchemeRequest);
}
/// <summary>
/// 批量修改拳探采购方案归属采购商
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
[HttpPost]
public IList<string> BatchUpdateQTPurchaseSchemeBelongPurchaser([FromBody]BatchUpdateQTPurchaseSchemeBelongPurchaserRequest request)
{
return purchaseSchemeBusiness.BatchUpdateQTPurchaseSchemeBelongPurchaser(request);
}
}
}

295
BBWY.Server.Business/PurchaseScheme/PurchaseProductAPIService.cs

@ -0,0 +1,295 @@
using BBWY.Common.Extensions;
using BBWY.Common.Http;
using BBWY.Common.Models;
using BBWY.Server.Model;
using BBWY.Server.Model.Db;
using BBWY.Server.Model.Dto;
using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text.RegularExpressions;
namespace BBWY.Server.Business
{
public class PurchaseProductAPIService : IDenpendency
{
private RestApiService restApiService;
private IMemoryCache memoryCache;
private string oneBoundKey = "t5060712539";
private string oneBoundSecret = "20211103";
//private string qtAppId = "BBWY2023022001";
//private string qtAppSecret = "908e131365d5448ca651ba20ed7ddefe";
private TimeSpan purchaseProductCacheTimeSpan;
//private TimeSpan _1688SessionIdTimeSpan;
//private ConcurrentDictionary<string, (Purchaser purchaser, IList<PurchaseSchemeProductSku> purchaseSchemeProductSkus)> productChaches;
private IDictionary<string, string> _1688ProductDetailRequestHeader;
private char[] skuPropertiesSplitChar = new char[] { ';' };
public PurchaseProductAPIService(RestApiService restApiService, IMemoryCache memoryCache)
{
this.memoryCache = memoryCache;
this.restApiService = restApiService;
_1688ProductDetailRequestHeader = new Dictionary<string, string>()
{
{ "Host","detail.1688.com"},
{ "User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Safari/537.36 Edg/104.0.1293.70"},
{ "Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"},
{ "Accept-Encoding","gzip, deflate, br"},
{ "Accept-Language","zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6"}
};
purchaseProductCacheTimeSpan = TimeSpan.FromDays(1);
}
public PurchaseSkuBasicInfoResponse GetProductInfo(PurchaseSkuBasicInfoRequest request)
{
var cacheKey = $"{request.PurchaseProductId}_{request.PriceMode}";
if (memoryCache.TryGetValue<PurchaseSkuBasicInfoResponse>(cacheKey, out var tuple))
return tuple.Copy();
PurchaseSkuBasicInfoResponse response = null;
if (request.FirstApiMode == Enums.PurchaseProductAPIMode.Spider)
{
response = LoadFromSpider(request);
if (response == null)
response = LoadFromOneBound(request);
}
else if (request.FirstApiMode == Enums.PurchaseProductAPIMode.OneBound)
{
response = LoadFromOneBound(request);
if (response == null)
response = LoadFromSpider(request);
}
if (response != null)
{
try
{
memoryCache.Set(cacheKey, response, purchaseProductCacheTimeSpan);
}
catch { }
}
return response?.Copy();
}
private PurchaseSkuBasicInfoResponse LoadFromOneBound(PurchaseSkuBasicInfoRequest request)
{
try
{
string platformStr = string.Empty;
if (request.Platform == Enums.Platform.)
platformStr = "1688";
if (string.IsNullOrEmpty(platformStr))
return null;
var result = restApiService.SendRequest("https://api-gw.onebound.cn/", $"{platformStr}/item_get", $"key={oneBoundKey}&secret={oneBoundSecret}&num_iid={request.PurchaseProductId}&lang=zh-CN&cache=no&agent={(request.PriceMode == Enums.PurchaseOrderMode.批发 ? 0 : 1)}", null, HttpMethod.Get, paramPosition: ParamPosition.Query, enableRandomTimeStamp: true);
if (result.StatusCode != System.Net.HttpStatusCode.OK)
throw new Exception($"{result.StatusCode} {result.Content}");
var jobject = JObject.Parse(result.Content);
var isOK = jobject.Value<string>("error_code") == "0000";
if (isOK)
{
var skuJArray = (JArray)jobject["item"]["skus"]["sku"];
if (skuJArray.Count == 0)
{
//errorMsg = $"商品{purchaseSchemeProduct.PurchaseProductId}缺少sku信息";
return null;
}
var list = skuJArray.Select(j => new PurchaseSkuItemBasicInfoResponse()
{
PurchaseProductId = request.PurchaseProductId,
Price = j.Value<decimal>("price"),
PurchaseSkuId = j.Value<string>("sku_id"),
PurchaseSkuSpecId = j.Value<string>("spec_id"),
Title = j.Value<string>("properties_name"),
Logo = GetOneBoundSkuLogo(j, (JArray)jobject["item"]["prop_imgs"]["prop_img"])
}).ToList();
var purchaserId = jobject["item"]["seller_info"].Value<string>("user_num_id");
var purchaserName = jobject["item"]["seller_info"].Value<string>("title");
if (string.IsNullOrEmpty(purchaserName))
purchaserName = jobject["item"]["seller_info"].Value<string>("shop_name");
var purchaserLocation = jobject["item"].Value<string>("location");
return new PurchaseSkuBasicInfoResponse()
{
Purchaser = new Model.Db.Purchaser()
{
Id = purchaserId,
Location = purchaserLocation,
Name = purchaserName,
Platform = request.Platform
},
ItemList = list,
PurchasePlatform = request.Platform,
PurchaseProductId = request.PurchaseProductId
};
}
}
catch { }
{
return null;
}
}
private string GetOneBoundSkuLogo(JToken skuJToken, JArray prop_img)
{
if (!prop_img.HasValues)
return "pack://application:,,,/Resources/Images/defaultItem.png";
var properties = skuJToken.Value<string>("properties").Split(skuPropertiesSplitChar, StringSplitOptions.RemoveEmptyEntries);
foreach (var p in properties)
{
var imgJToken = prop_img.FirstOrDefault(g => g.Value<string>("properties") == p);
if (imgJToken != null)
return imgJToken.Value<string>("url");
}
return "pack://application:,,,/Resources/Images/defaultItem.png";
}
private PurchaseSkuBasicInfoResponse LoadFromSpider(PurchaseSkuBasicInfoRequest request)
{
switch (request.Platform)
{
case Enums.Platform.:
return LoadFrom1688Spider(request);
//case Platform.拳探:
// return LoadFromQTSpider(platform, productId, skuId, purchaseProductId, priceMode);
}
return null;
}
private PurchaseSkuBasicInfoResponse LoadFrom1688Spider(PurchaseSkuBasicInfoRequest request)
{
//https://detail.1688.com/offer/672221374773.html?clickid=65f3772cd5d16f190ce4991414607&sessionid=3de47a0c26dcbfde4692064bd55861&sk=order
//globalData/tempModel/sellerUserId
//globalData/tempModel/companyName
//data/1081181309101/data/location
//data/1081181309582/data/pirceModel/[currentPrices]/[0]price
try
{
var _1688pageResult = restApiService.SendRequest("https://detail.1688.com",
$"offer/{request.PurchaseProductId}.html",
$"clickid={Guid.NewGuid().ToString().Md5Encrypt()}&sessionid={Guid.NewGuid().ToString().Md5Encrypt()}&sk={(request.PriceMode == Enums.PurchaseOrderMode.批发 ? "order" : "consign")}",
_1688ProductDetailRequestHeader,
HttpMethod.Get,
httpClientName: "gzip");
if (_1688pageResult.StatusCode != System.Net.HttpStatusCode.OK)
return null;
var match = Regex.Match(_1688pageResult.Content, @"(window\.__INIT_DATA=)(.*)(\r*\n*\s*</script>)");
if (!match.Success)
return null;
var jsonStr = match.Groups[2].Value;
var jobject = JObject.Parse(jsonStr);
//16347413030323
var purchaser = new Purchaser()
{
Id = jobject["globalData"]["tempModel"]["sellerUserId"].ToString(),
Name = jobject["globalData"]["tempModel"]["companyName"].ToString(),
Location = jobject["data"]["1081181309101"] != null ?
jobject["data"]["1081181309101"]["data"]["location"].ToString() :
jobject["data"]["16347413030323"]["data"]["location"].ToString(),
Platform = Enums.Platform.
};
var colorsProperty = jobject["globalData"]["skuModel"]["skuProps"].FirstOrDefault(j => j.Value<int>("fid") == 3216 ||
j.Value<int>("fid") == 1627207 ||
j.Value<int>("fid") == 1234 ||
j.Value<int>("fid") == 3151)["value"]
.Children()
.Select(j => new
{
name = j.Value<string>("name"),
imageUrl = j.Value<string>("imageUrl")
}).ToList();
var firstPrice = jobject["data"]["1081181309582"] != null ?
jobject["data"]["1081181309582"]["data"]["priceModel"]["currentPrices"][0].Value<decimal>("price") :
jobject["data"]["16347413030316"]["data"]["priceModel"]["currentPrices"][0].Value<decimal>("price");
var list = new List<PurchaseSkuItemBasicInfoResponse>();
foreach (var jsku in jobject["globalData"]["skuModel"]["skuInfoMap"].Children())
{
var jskuProperty = jsku as JProperty;
var name = jskuProperty.Name;
var matchName = name.Contains("&gt;") ? name.Substring(0, name.IndexOf("&gt;")) : name;
var value = jskuProperty.Value;
var skuPrice = value.Value<decimal>("price");
list.Add(new PurchaseSkuItemBasicInfoResponse()
{
PurchaseProductId = request.PurchaseProductId,
Price = skuPrice == 0M ? firstPrice : skuPrice,
Title = name,
PurchaseSkuId = value.Value<string>("skuId"),
PurchaseSkuSpecId = value.Value<string>("specId"),
Logo = colorsProperty.FirstOrDefault(c => c.name == matchName)?.imageUrl ?? "pack://application:,,,/Resources/Images/defaultItem.png"
});
}
return new PurchaseSkuBasicInfoResponse()
{
ItemList = list,
Purchaser = purchaser,
PurchaseProductId = request.PurchaseProductId,
PurchasePlatform = Enums.Platform.
};
}
catch
{
return null;
}
}
//private (Purchaser purchaser, IList<PurchaseSchemeProductSku> purchaseSchemeProductSkus)? LoadFromQTSpider(Platform platform, string productId, string skuId, string purchaseProductId, PurchaseOrderMode priceMode)
//{
// try
// {
// var response = quanTanProductClient.GetProductInfo(purchaseProductId, qtAppId, qtAppSecret);
// if (response.Status != 200)
// return null;
// return (new Purchaser()
// {
// Id = response.Data.Supplier.VenderId,
// Name = response.Data.Supplier.VerdenName,
// Location = response.Data.Supplier.Location
// }, response.Data.ProductSku.Select(qtsku => new PurchaseSchemeProductSku()
// {
// ProductId = productId,
// SkuId = skuId,
// PurchaseProductId = purchaseProductId,
// Price = qtsku.Price,
// Title = qtsku.Title,
// PurchaseSkuId = qtsku.SkuId,
// PurchaseSkuSpecId = string.Empty,
// Logo = qtsku.Logo
// }).ToList());
// }
// catch
// {
// return null;
// }
//}
}
}

109
BBWY.Server.Business/PurchaseScheme/PurchaseSchemeBusiness.cs

@ -1,7 +1,9 @@
using BBWY.Common.Extensions;
using BBWY.Common.Models;
using BBWY.Server.Model;
using BBWY.Server.Model.Db;
using BBWY.Server.Model.Dto;
using FreeSql;
using System;
using System.Collections.Generic;
using System.Linq;
@ -11,7 +13,11 @@ namespace BBWY.Server.Business
{
public class PurchaseSchemeBusiness : BaseBusiness, IDenpendency
{
public PurchaseSchemeBusiness(IFreeSql fsql, NLogManager nLogManager, IIdGenerator idGenerator) : base(fsql, nLogManager, idGenerator) { }
private PurchaseProductAPIService purchaseProductAPIService;
public PurchaseSchemeBusiness(IFreeSql fsql, NLogManager nLogManager, IIdGenerator idGenerator, PurchaseProductAPIService purchaseProductAPIService) : base(fsql, nLogManager, idGenerator)
{
this.purchaseProductAPIService = purchaseProductAPIService;
}
private void ExtractNewPurchaser<T>(IList<T> purchaserSchemeList, IList<Purchaser> addPurchaserList) where T : InputPurchaseSchemeRequest
{
@ -223,7 +229,7 @@ namespace BBWY.Server.Business
var purchaserList = fsql.Select<Purchaser>().Where(p => sharePurchaserIdList.Contains(p.Id)).ToList();
foreach (var p in purchaserList)
{
var scheme = purchaseSchemeList.FirstOrDefault(ps=>ps.PurchaserId == p.Id);
var scheme = purchaseSchemeList.FirstOrDefault(ps => ps.PurchaserId == p.Id);
if (scheme != null)
{
p.DefaultCost = scheme.DefaultCost;
@ -255,5 +261,104 @@ namespace BBWY.Server.Business
fsql.Delete<PurchaseSchemeProductSku>().Where(p => p.SkuPurchaseSchemeId == schemeId).ExecuteAffrows();
});
}
/// <summary>
/// 获取采购Sku的基本信息
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
public PurchaseSkuBasicInfoResponse GetPurchaseSkuBasicInfo(PurchaseSkuBasicInfoRequest request)
{
return purchaseProductAPIService.GetProductInfo(request);
}
public IList<PurchaseSkuBasicInfoResponse> BatchGetPurchaseSkuBasicInfo(BatchPurchaseSkuBasicInfoRequest request)
{
var list = new List<PurchaseSkuBasicInfoResponse>();
foreach (var param in request.Params)
{
foreach (var purchaseId in param.PurchaseProductIds)
{
var response = GetPurchaseSkuBasicInfo(new PurchaseSkuBasicInfoRequest()
{
FirstApiMode = request.FirstApiMode,
PriceMode = request.PriceMode,
Platform = param.Platform,
PurchaseProductId = purchaseId
});
if (response != null)
{
if (param.PurchaseSkuIds != null && param.PurchaseSkuIds.Count() > 0)
{
for (var i = 0; i < response.ItemList.Count(); i++)
{
var skuInfo = response.ItemList[i];
if (!param.PurchaseSkuIds.Any(s => s == skuInfo.PurchaseSkuId))
{
response.ItemList.RemoveAt(i);
i--;
}
}
}
list.Add(response);
}
}
}
return list;
}
/// <summary>
/// 批量修改拳探采购方案归属采购商
/// </summary>
/// <param name="request">修改成功的拳探skuId</param>
/// <returns></returns>
public IList<string> BatchUpdateQTPurchaseSchemeBelongPurchaser(BatchUpdateQTPurchaseSchemeBelongPurchaserRequest request)
{
var purchaseSchemeList = GetPurchaseSchemeList(new QuerySchemeRequest()
{
PurchasePlatform = Enums.Platform.,
PurchaserId = request.PurchaserId
});
IList<string> updateSkuIdList = new List<string>();
IList<IUpdate<PurchaseScheme>> updatePurchaseSchemeList = new List<IUpdate<PurchaseScheme>>();
foreach (var purchaseScheme in purchaseSchemeList)
{
var firstProduct = purchaseScheme.PurchaseSchemeProductList.FirstOrDefault();
var purchaseBasicInfoList = BatchGetPurchaseSkuBasicInfo(new BatchPurchaseSkuBasicInfoRequest()
{
FirstApiMode = Enums.PurchaseProductAPIMode.Spider,
PriceMode = Enums.PurchaseOrderMode.,
Params = new List<BatchPurchaseSkuBasicInfoParamRequest>()
{
new BatchPurchaseSkuBasicInfoParamRequest()
{
Platform = Enums.Platform.,
PurchaseProductIds = new string[]{firstProduct.PurchaseProductId}
}
}
});
if (purchaseBasicInfoList.Count() == 0)
continue;
var p = purchaseBasicInfoList.FirstOrDefault().Purchaser;
if (p != null && p.Id != purchaseScheme.PurchaserId)
{
var update = fsql.Update<PurchaseScheme>(purchaseScheme.Id).Set(ps => ps.PurchaserId, p.Id);
updatePurchaseSchemeList.Add(update);
updateSkuIdList.Add(purchaseScheme.SkuId);
}
}
if (updatePurchaseSchemeList.Count() > 0)
{
fsql.Transaction(() =>
{
foreach (var update in updatePurchaseSchemeList)
update.ExecuteAffrows();
});
}
return updateSkuIdList;
}
}
}

10
BBWY.Server.Model/Dto/Request/PurchaseScheme/BatchUpdateQTPurchaseSchemeBelongPurchaserRequest.cs

@ -0,0 +1,10 @@
namespace BBWY.Server.Model.Dto
{
public class BatchUpdateQTPurchaseSchemeBelongPurchaserRequest
{
/// <summary>
/// 采购商Id 可空
/// </summary>
public string PurchaserId { get; set; }
}
}

42
BBWY.Server.Model/Dto/Request/PurchaseScheme/PurcasheSkuBasicInfoRequest.cs

@ -0,0 +1,42 @@
using System.Collections.Generic;
namespace BBWY.Server.Model.Dto
{
public class PurchaseSkuBasicInfoRequest
{
public Enums.Platform Platform { get; set; }
/// <summary>
/// 采购商品Id
/// </summary>
public string PurchaseProductId { get; set; }
public Enums.PurchaseOrderMode PriceMode { get; set; }
public Enums.PurchaseProductAPIMode FirstApiMode { get; set; }
}
public class BatchPurchaseSkuBasicInfoRequest
{
public IList<BatchPurchaseSkuBasicInfoParamRequest> Params { get; set; }
public Enums.PurchaseOrderMode PriceMode { get; set; }
public Enums.PurchaseProductAPIMode FirstApiMode { get; set; }
}
public class BatchPurchaseSkuBasicInfoParamRequest
{
public Enums.Platform Platform { get; set; }
/// <summary>
/// 采购商品Id(采购spu)
/// </summary>
public string[] PurchaseProductIds { get; set; }
/// <summary>
/// 需要保留的采购SkuId,如果传递了该数组,将过滤不在该数组的采购sku
/// </summary>
public string[] PurchaseSkuIds { get; set; }
}
}

58
BBWY.Server.Model/Dto/Response/PurchaseScheme/PurchaseProductBasicInfoResponse.cs

@ -0,0 +1,58 @@
using BBWY.Server.Model.Db;
using System.Collections.Generic;
namespace BBWY.Server.Model.Dto
{
/// <summary>
/// 采购Sku基础信息对象
/// </summary>
public class PurchaseSkuBasicInfoResponse
{
public Enums.Platform PurchasePlatform { get; set; }
public string PurchaseProductId { get; set; }
/// <summary>
/// 采购SKU基础信息列表
/// </summary>
public IList<PurchaseSkuItemBasicInfoResponse> ItemList { get; set; }
/// <summary>
/// 采购商
/// </summary>
public Purchaser Purchaser { get; set; }
}
/// <summary>
/// 采购Sku基础信息对象
/// </summary>
public class PurchaseSkuItemBasicInfoResponse
{
/// <summary>
/// 采购SPU
/// </summary>
public string PurchaseProductId { get; set; }
/// <summary>
/// 采购SKU
/// </summary>
public string PurchaseSkuId { get; set; }
/// <summary>
/// 采购SPEC 1688独有属性 下单需要
/// </summary>
public string PurchaseSkuSpecId { get; set; }
/// <summary>
/// SKU标题
/// </summary>
public string Title { get; set; }
public string Logo { get; set; }
/// <summary>
/// 单价
/// </summary>
public decimal Price { get; set; }
}
}

9
BBWY.Server.Model/Enums.cs

@ -33,6 +33,15 @@
= 1
}
/// <summary>
/// 采购商品API模式 Spider = 0,OneBound = 1
/// </summary>
public enum PurchaseProductAPIMode
{
Spider = 0,
OneBound = 1
}
/// <summary>
/// 仓储类型
/// </summary>

Loading…
Cancel
Save