RepositoryExtension.Supplier.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. using System.Net.Http;
  2. using System;
  3. using System.Threading.Tasks;
  4. using Wicture.DbRESTFul.Infrastructure.Repository;
  5. using static JiaZhiQuan.Common.YCTech.YCTechModel;
  6. using JiaZhiQuan.Common.Config;
  7. using System.Linq;
  8. using JiaZhiQuan.Common.Utils;
  9. using Wicture.DbRESTFul;
  10. using System.Collections.Generic;
  11. using System.Data;
  12. using Wicture.DbRESTFul.Cache;
  13. namespace JiaZhiQuan.Common
  14. {
  15. /// <summary>
  16. /// 供应商
  17. /// </summary>
  18. public static partial class RepositoryExtension
  19. {
  20. /// <summary>
  21. /// 同步供应商商品
  22. /// </summary>
  23. /// <param name="repository"></param>
  24. /// <param name="conn"></param>
  25. /// <param name="httpClientFactory"></param>
  26. /// <param name="config"></param>
  27. /// <param name="cacheProvider"></param>
  28. /// <param name="isDev"></param>
  29. /// <param name="supplierName"></param>
  30. /// <returns></returns>
  31. /// <exception cref="LogicalException"></exception>
  32. public static async Task<bool> SupplierGoodsSync(this DbRESTFulRepository repository, IDbConnection conn, IHttpClientFactory httpClientFactory, ConfigFromDb config, bool isDev, string supplierName)
  33. {
  34. bool hasChange = false;
  35. var supplier = await repository.QuerySingleOrDefaultAsync<dynamic>("select supplierId,supplierName from n_supplier where supplierName=@supplierName and state=0", new { supplierName });
  36. if (supplier == null) throw new LogicalException("未找到该供应商");
  37. int supplierId = (int)supplier.supplierId;
  38. var now = DateTime.Now;
  39. string syncRst = "同步于初科技商品失败,调用商品接口失败";
  40. //调用商品接口
  41. var httpClient = httpClientFactory.CreateClient();
  42. var request = new YCTechSyncProductRequest
  43. {
  44. Timestamp = DateTime.Now.ToString("yyyyMMddHHmmssfff")
  45. };
  46. await request.ExeRequest(httpClient, config);
  47. if (request.Response != null && request.Response.Code != "-99" && request.Response.Data != null && request.Response.Data.Any())
  48. {
  49. var supplierGoods = request.Response.Data.Select(g => new SupplierGoods()
  50. {
  51. productId = (int)g.Id,
  52. productName = g.ProductName,
  53. supplierId = supplierId,
  54. supplierName = supplierName,
  55. originalPrice = AmountUtils.ConvertYuanToCent((decimal)g.MianZhi),
  56. purchasePrice = AmountUtils.ConvertYuanToCent((decimal)g.ShouJia),
  57. pricingType = g.JiJiaLX,
  58. pricing = (int)(g.JiJia * 10000)
  59. }).ToList();
  60. var goodsList = await repository.QueryAsync<SupplierGoods>(@"select
  61. productId,
  62. productName,
  63. supplierId,
  64. originalPrice,
  65. purchasePrice ,
  66. pricingType,
  67. pricing
  68. from n_supplier_goods where supplierId=@supplierId"
  69. , new { supplierId });
  70. //日志数据
  71. List<SupplierGoodsChangeLog> logList = new List<SupplierGoodsChangeLog>();
  72. //需要删除的数据
  73. List<int> delIds = new List<int>();
  74. List<SupplierGoods> addedItems = new List<SupplierGoods>();
  75. List<SupplierGoods> updatedItems = new List<SupplierGoods>();
  76. if (goodsList != null && goodsList.Any())
  77. {
  78. //转化成字典进行比较
  79. var oldDict = goodsList.ToDictionary(item => item.productId);
  80. var newDict = supplierGoods.ToDictionary(item => item.productId);
  81. //新增的数据
  82. addedItems = supplierGoods.Where(nItem => !oldDict.ContainsKey(nItem.productId)).ToList();
  83. if (addedItems.Any())
  84. {
  85. addedItems.ForEach(a =>
  86. {
  87. logList.Add(new SupplierGoodsChangeLog
  88. {
  89. type = 0,
  90. syncId = 0,
  91. productId = a.productId,
  92. productName = a.productName,
  93. content = $"{supplierName},新增“{a.productId}”,{a.productName},原价{a.originalPrice}元," +
  94. $"优惠{a.pricingType}{a.pricing},采购价{a.purchasePrice}元",
  95. createAt = now
  96. });
  97. });
  98. }
  99. //删除的数据
  100. var deletedItems = goodsList.Where(oItem => !newDict.ContainsKey(oItem.productId)).ToList();
  101. if (deletedItems.Any())
  102. {
  103. deletedItems.ForEach(a =>
  104. {
  105. delIds.Add(a.productId);
  106. logList.Add(new SupplierGoodsChangeLog
  107. {
  108. type = 1,
  109. syncId = 0,
  110. productId = a.productId,
  111. productName = a.productName,
  112. content = $"{supplierName},减少“{a.productId}”,{a.productName},原价{a.originalPrice}元," +
  113. $"优惠{a.pricingType}{a.pricing},采购价{a.purchasePrice}元",
  114. createAt = now
  115. });
  116. });
  117. }
  118. //更新的商品
  119. updatedItems = supplierGoods.Where(nItem =>
  120. {
  121. if (oldDict.TryGetValue(nItem.productId, out var oItem))
  122. {
  123. return !AreEqual(oItem, nItem);
  124. }
  125. return false;
  126. }).ToList();
  127. if (updatedItems.Any())
  128. {
  129. updatedItems.ForEach(a =>
  130. {
  131. var oldGoods = goodsList.FirstOrDefault(g => g.productId == a.productId);
  132. if (oldGoods != null)
  133. {
  134. logList.Add(new SupplierGoodsChangeLog
  135. {
  136. type = 2,
  137. syncId = 0,
  138. productId = a.productId,
  139. productName = a.productName,
  140. content = $"{supplierName},“{a.productId},{oldGoods.productName}“从“原价{oldGoods.originalPrice}元," +
  141. $"优惠{oldGoods.pricingType}{oldGoods.pricing},采购价{oldGoods.purchasePrice}元“变更为" +
  142. $"“原价{a.originalPrice}元,优惠{a.pricingType}{a.pricing},采购价{a.purchasePrice}元”",
  143. createAt = now
  144. });
  145. }
  146. });
  147. }
  148. }
  149. else addedItems = supplierGoods;
  150. var trans = conn.BeginTransaction();
  151. try
  152. {
  153. //新增的数据
  154. if (addedItems.Any())
  155. {
  156. await repository.QuerySingleOrDefaultAsync<int>($@"INSERT INTO
  157. n_supplier_goods(
  158. productId,
  159. productName,
  160. supplierId,
  161. originalPrice,
  162. purchasePrice,
  163. pricingType,
  164. pricing,
  165. onsaleState,
  166. createAt)VALUES(@productId,
  167. @productName,
  168. @supplierId,
  169. @originalPrice,
  170. @purchasePrice,
  171. @pricingType,
  172. @pricing,
  173. {(int)MallGoodsOnsaleState.上架},
  174. @createAt)", addedItems, conn, trans);
  175. }
  176. //更新的数据
  177. if (updatedItems.Any())
  178. {
  179. await repository.QuerySingleOrDefaultAsync<int>($@"update n_supplier_goods
  180. set onsaleState={(int)MallGoodsOnsaleState.上架},
  181. productName=@productName,
  182. supplierId=@supplierId,
  183. originalPrice=@originalPrice,
  184. purchasePrice=@purchasePrice,
  185. pricingType=@pricingType,
  186. pricing=@pricing,
  187. updateAt=@updateAt
  188. where productId=@productId", updatedItems, conn, trans);
  189. }
  190. //删除的数据
  191. if (delIds.Any())
  192. {
  193. await repository.QuerySingleOrDefaultAsync<int>($"update n_supplier_goods set onsaleState={(int)MallGoodsOnsaleState.下架} where productId in @productId", new { productId = delIds }, conn, trans);
  194. }
  195. //改动日志数据
  196. if (logList.Any())
  197. {
  198. int syncId = await repository.QuerySingleOrDefaultAsync<int>(@"insert into n_supplier_goods_sync(supplierId,state,syncRst,createAt)
  199. values (@supplierId,@state,@syncRst,@createAt);select LAST_INSERT_ID();", new { supplierId, state = 1, syncRst = "同步成功", createAt = now }, conn, trans);
  200. logList.ForEach(l => { l.syncId = syncId; });
  201. await repository.QuerySingleOrDefaultAsync<int>($@"INSERT INTO
  202. n_supplier_goods_change_records(
  203. syncId,
  204. type,
  205. productId,
  206. productName,
  207. content,
  208. createAt)VALUES(
  209. @syncId,
  210. @type,
  211. @productId,
  212. @productName,
  213. @content,
  214. @createAt)", logList, conn, trans);
  215. hasChange = true;
  216. }
  217. trans.Commit();
  218. // 如果有变化发送邮件给运营
  219. if (hasChange)
  220. {
  221. SendEmail(config, isDev);
  222. }
  223. return true;
  224. }
  225. catch (Exception ex)
  226. {
  227. trans.Rollback();
  228. syncRst = "同步于初科技商品失败" + "\r\n" + ex.Message;
  229. LoggerManager.Logger.Error(ex, "同步于初科技商品失败" + "\r\n" + ex.Message);
  230. }
  231. }
  232. await repository.QuerySingleOrDefaultAsync<int>(@"insert into n_supplier_goods_sync(supplierId,state,syncRst,createAt)
  233. values (@supplierId,@state,@syncRst,@createAt);", new { supplierId, state = 0, syncRst, createAt = now });
  234. LoggerManager.Logger.Error("", syncRst);
  235. return false;
  236. }
  237. /// <summary>
  238. /// 同步供应商余额
  239. /// </summary>
  240. /// <param name="repository"></param>
  241. /// <param name="httpClientFactory"></param>
  242. /// <param name="config"></param>
  243. /// <param name="supplierName"></param>
  244. /// <returns></returns>
  245. public static async Task<bool> SyncYCTechSupplierBalance(this DbRESTFulRepository repository, IHttpClientFactory httpClientFactory, ConfigFromDb config, string supplierName = "于初科技", bool isSyncAt = true)
  246. {
  247. var supplier = await repository.QuerySingleOrDefaultAsync<dynamic>("select supplierId,supplierName from n_supplier where supplierName=@supplierName and state=0", new { supplierName });
  248. if (supplier != null)
  249. {
  250. int supplierId = (int)supplier.supplierId;
  251. //查询余额
  252. var httpClient = httpClientFactory.CreateClient();
  253. var request = new YCTechYuERequest
  254. {
  255. Timestamp = DateTime.Now.ToString("yyyyMMddHHmmssfff")
  256. };
  257. await request.ExeRequest(httpClient, config);
  258. if (request.Response != null && request.Response.Code != "-99")
  259. {
  260. int currentBalance = (int)(request.Response.Data.SurplusYuE * 100);
  261. string atSql = "";
  262. if (isSyncAt) atSql = ",syncAt=now()";
  263. await repository.QuerySingleOrDefaultAsync<int>($"update n_supplier set balance=@balance {atSql} where supplierId=@supplierId", new { supplierId, balance = currentBalance });
  264. return true;
  265. }
  266. }
  267. LoggerManager.Logger.Error("", "获取供应商余额失败");
  268. return false;
  269. }
  270. /// <summary>
  271. /// 比较商品内容是否变化
  272. /// </summary>
  273. /// <param name="item1"></param>
  274. /// <param name="item2"></param>
  275. /// <returns></returns>
  276. private static bool AreEqual(SupplierGoods item1, SupplierGoods item2)
  277. {
  278. return item1.productName == item2.productName &&
  279. item1.originalPrice == item2.originalPrice &&
  280. item1.purchasePrice == item2.purchasePrice &&
  281. item1.pricingType == item2.pricingType &&
  282. item1.pricing == item2.pricing;
  283. }
  284. private static void SendEmail(ConfigFromDb config, bool isDev)
  285. {
  286. if (!string.IsNullOrEmpty(config.MPPostStatWarningMailTo))
  287. {
  288. // 通过邮件提醒
  289. var cont = "供应商商品有变化,请登录管理后台查看";
  290. var mailToDic = new Dictionary<string, string>();
  291. config.MPPostStatWarningMailTo.Split(',', StringSplitOptions.RemoveEmptyEntries).ForEach(e => mailToDic[e] = e);
  292. var env = isDev ? "【测试环境】" : "【正式环境】";
  293. _ = CommonUtils.SendEmail(new MailInfo
  294. {
  295. Account = config.MailAccount,
  296. MailFromAddr = config.MailAccount,
  297. AuthCode = config.MailAuthCode,
  298. MailFromName = "JiaZhiQuan.Processor",
  299. MailToDic = mailToDic,
  300. Subject = env + cont,
  301. Content = env + cont
  302. });
  303. }
  304. }
  305. private class SupplierGoods
  306. {
  307. public int productId { get; set; }
  308. public string productName { get; set; }
  309. public int supplierId { get; set; }
  310. public string supplierName { get; set; }
  311. public int originalPrice { get; set; }
  312. public int purchasePrice { get; set; }
  313. public string pricingType { get; set; }
  314. public int pricing { get; set; }
  315. public DateTime createAt { get; set; } = DateTime.Now;
  316. public DateTime updateAt { get; set; } = DateTime.Now;
  317. }
  318. private class SupplierGoodsChangeLog
  319. {
  320. public int type { get; set; }
  321. public int syncId { get; set; }
  322. public int productId { get; set; }
  323. public string productName { get; set; }
  324. public string content { get; set; }
  325. public DateTime createAt { get; set; } = DateTime.Now;
  326. }
  327. }
  328. }