using BBWYB.Common.Extensions; using BBWYB.Common.Log; using BBWYB.Common.Models; using BBWYB.Server.Model; using BBWYB.Server.Model.Db; using BBWYB.Server.Model.Db.BBWY; using BBWYB.Server.Model.Db.SpuOptimization; using BBWYB.Server.Model.Dto; using FreeSql; using Newtonsoft.Json; using Org.BouncyCastle.Asn1; using System.Numerics; using System.Text.RegularExpressions; using Yitter.IdGenerator; namespace BBWYB.Server.Business { public class OptimizationBusiness : BaseBusiness, IDenpendency { private FreeSqlMultiDBManager fsqlManager; private VenderBusiness venderBusiness; private TimeLimitRules timeLimitRules; private UserBusiness userBusiness; private PurchaseSchemeBusiness purchaseSchemeBusiness; public OptimizationBusiness(IFreeSql fsql, NLogManager nLogManager, IIdGenerator idGenerator, FreeSqlMultiDBManager fsqlManager, VenderBusiness venderBusiness, TimeLimitRules timeLimitRules, UserBusiness userBusiness, PurchaseSchemeBusiness purchaseSchemeBusiness) : base(fsql, nLogManager, idGenerator) { this.fsqlManager = fsqlManager; this.venderBusiness = venderBusiness; this.timeLimitRules = timeLimitRules; this.userBusiness = userBusiness; this.purchaseSchemeBusiness = purchaseSchemeBusiness; } public Enums.TriggerOptimizationReason? GetOptimizationReason(SpuTotalSaleInfo s) { if (s.IsFirstPurchaseCompleted == false) return Enums.TriggerOptimizationReason.首次采购; if (s.IsFirstPurchaseCompleted == true && s.IsFirstOptimizationCompleted == false) { if (s.ItemCount - s.FirstPurchaseCompletedItemCount >= 20) return Enums.TriggerOptimizationReason.首次优化; if (s.LastOptimizationTime != null && (DateTime.Now.Date - s.LastOptimizationTime.Value.Date).TotalDays > 30) return Enums.TriggerOptimizationReason.首次优化; } if (s.IsFirstOptimizationCompleted == true) { if (s.LastOptimizationItemCount != 0 && s.ItemCount * 1.0 / s.LastOptimizationItemCount >= 2) return Enums.TriggerOptimizationReason.再次优化; if (s.LastOptimizationTime != null && (DateTime.Now.Date - s.LastOptimizationTime.Value.Date).TotalDays > 30) return Enums.TriggerOptimizationReason.再次优化; } return null; } /// /// 良库预警 /// /// /// public void LKInventoryAlertNotification(BatchLKInventoryAlertRequest request) { nLogManager.Default().Info($"LKInventoryAlertNotification {JsonConvert.SerializeObject(request)}"); #region 确定JDSKU对应的拳探SKU和拳探SPU var jdSkuIdList = request.Items.Select(x => x.Sku).Distinct().ToList(); var jdqtskuList = fsqlManager.BBWYCfsql.Select() .Where(ps1 => ps1.ShopId == request.ShopId && jdSkuIdList.Contains(ps1.SkuId)) .GroupBy(ps1 => ps1.SkuId) .WithTempQuery(g => new { MaxId = g.Max(g.Value.Id) }) .From() .InnerJoin((ps1, ps2) => ps1.MaxId == ps2.Id) .ToList((ps1, ps2) => ps2); var qtSkuIdList = jdqtskuList.Select(x => x.PurchaseSkuIds).Distinct().ToList(); var productSkuList = fsql.Select(qtSkuIdList).ToList(); if (productSkuList.Count() == 0) return; var shopId = productSkuList.FirstOrDefault()?.ShopId; var productIdList = productSkuList.Select(ps => ps.ProductId).Distinct().ToList(); var productList = fsql.Select(productIdList).ToList(); var dbSpuTotalInfoList = fsql.Select().Where(spi => productIdList.Contains(spi.ProductId)).ToList(); #endregion //查询已存在未结束的优化任务 var dbSpuOptimizationTaskList = fsql.Select() .Where(t => t.ShopId == shopId && t.IsOptimizationCompleted == false && productIdList.Contains(t.ProductId)) .ToList(); //优化历史 var dbSpuOptimizationHistoryList = fsql.Select() .Where(s1 => productIdList.Contains(s1.ProductId) && s1.IsOptimizationCompleted == true) .GroupBy(s1 => s1.ProductId) .WithTempQuery(g => new { MaxId = g.Max(g.Value.Id) }) .From() .InnerJoin((s1, s2) => s1.MaxId == s2.Id) .ToList((s1, s2) => s2); #region DB Operation List insertSpuOptimizationTaskList = new List(); List insertSkuOptimizationTaskList = new List(); List insertSpuOptimizationBargainTeamTaskList = new List(); List insertSpuOptimizationCompetitiveTenderTaskList = new List(); //List insertSpuOptimizationPurchaserCompetitiveTenderTaskList = new List(); List insertTimeLimitTaskList = new List(); #endregion var belongShop = venderBusiness.GetShopList(request.ShopId).FirstOrDefault(); if (belongShop == null) throw new BusinessException("店铺不存在"); var bargainTeamList = venderBusiness.GetYiJiaGroup(); //获取议价组 var bargainTeamIdList = bargainTeamList.Select(t => t.Id).ToList(); var waitToCompetitiveTenderSchemeList = fsql.Select() .Where(ps => bargainTeamIdList.Contains(ps.BelongBargainTeamId) && productIdList.Contains(ps.ProductId)) .ToList(); //需要参与竞标采购方案 var waitToCompetitiveTenderSchemeIdList = waitToCompetitiveTenderSchemeList.Select(ps => ps.Id).ToList(); var waitToCompetitiveTenderSchemePurchaserList = fsql.Select() .Where(psp => waitToCompetitiveTenderSchemeIdList.Contains(psp.SkuPurchaseSchemeId)) .GroupBy(psp => new { psp.SkuPurchaseSchemeId, psp.PurchaserId }) .ToList(g => new { g.Key.SkuPurchaseSchemeId, g.Key.PurchaserId }); //需要参与竞标的采购商 foreach (var productId in productIdList) { #region 验证 if (dbSpuOptimizationTaskList.Any(s => s.ProductId == productId)) //过滤未结束的spu任务 continue; var spuTotalInfo = dbSpuTotalInfoList.FirstOrDefault(psi => psi.ProductId == productId); //spu销量 if (spuTotalInfo == null) continue; var reason = GetOptimizationReason(spuTotalInfo); //过滤不需要优化的spu if (reason == null) continue; #endregion var skuOptimizationHistory = dbSpuOptimizationHistoryList.FirstOrDefault(h => h.ProductId == productId); //优化历史 #region qtsku - jdsku 关系匹配 var currentProductSkuList = productSkuList.Where(ps => ps.ProductId == productId && jdqtskuList.Any(x => x.PurchaseSkuIds == ps.Id)).ToList(); if (currentProductSkuList.Count() == 0) continue; //拳探sku-京东sku下单关系映射表 var mappingQT_JDSKUDictionary = new Dictionary(); foreach (var ps in currentProductSkuList) { var jdsku = jdqtskuList.FirstOrDefault(x => x.PurchaseSkuIds == ps.Id)?.SkuId; if (string.IsNullOrEmpty(jdsku)) continue; if (!mappingQT_JDSKUDictionary.ContainsKey(ps.Id)) mappingQT_JDSKUDictionary.TryAdd(ps.Id, jdsku); } var jdskus = mappingQT_JDSKUDictionary.Values.ToList(); var qtskus = mappingQT_JDSKUDictionary.Keys.ToList(); #endregion #region 读取JDSKU预估金额 var jdskuRecentCostList = fsqlManager.BBWYCfsql.Select(jdskus).ToList(); #endregion #region 创建SPU优化任务 var spuOptimizationTask = new SpuOptimizationTask() { Id = idGenerator.NewLong(), BelongShopId = long.Parse(belongShop.ShopId), BelongShopName = belongShop.ShopName, CompletionTime = null, CreateTime = DateTime.Now, IsOptimizationCompleted = false, LastOptimizationTime = null, ProductId = productId, ShopId = shopId, ProductTitle = productList.FirstOrDefault(p => p.Id == productId)?.ProductName, TriggerOptimizationReason = reason, PreSkuCount = jdskus.Count(), PreItemCount = 0, PrePurchaseAmount = 0M }; insertSpuOptimizationTaskList.Add(spuOptimizationTask); #endregion #region 创建SKU优化任务 foreach (var sku in mappingQT_JDSKUDictionary.Keys) { mappingQT_JDSKUDictionary.TryGetValue(sku, out string jdSkuId); var requestSkuItem = request.Items.FirstOrDefault(x => x.Sku == jdSkuId); if (requestSkuItem == null) continue; var preItemCount = requestSkuItem.PreItemCount; var prePurchaseAmount = 0M; if (!string.IsNullOrEmpty(jdSkuId)) { var jdSkuRecentCost = jdskuRecentCostList.FirstOrDefault(x => x.SkuId == jdSkuId); if (jdSkuRecentCost != null) { prePurchaseAmount = (jdSkuRecentCost.SingleSkuAmount ?? 0M + jdSkuRecentCost.SingleFirstFreight ?? 0M + jdSkuRecentCost.SingleFreight ?? 0M + jdSkuRecentCost.SingleDeliveryFreight ?? 0M + jdSkuRecentCost.SingleConsumableAmount ?? 0M + jdSkuRecentCost.SingleInStorageAmount ?? 0M + jdSkuRecentCost.SingleOutStorageAmount ?? 0M + jdSkuRecentCost.SinglePackagingLaborAmount ?? 0M + jdSkuRecentCost.SingleOperationAmount ?? 0M) * preItemCount; } } var skuOptimizationTask = new SkuOptimizationTask() { Id = idGenerator.NewLong(), CreateTime = DateTime.Now, JDSkuId = jdSkuId, PreItemCount = preItemCount, SkuId = sku, SpuOptimizationTaskId = spuOptimizationTask.Id, PrePurchaseAmount = prePurchaseAmount }; insertSkuOptimizationTaskList.Add(skuOptimizationTask); //累计spu优化任务信息 spuOptimizationTask.PreItemCount += preItemCount; spuOptimizationTask.PrePurchaseAmount += prePurchaseAmount; } #endregion #region 创建SPU优化议价组任务 foreach (var department in bargainTeamList) { var spuOptimizationBargainTeamTask = new SpuOptimizationBargainTeamTask() { Id = idGenerator.NewLong(), BelongTeamId = department.Id, BelongTeamName = department.DepartmentName, CompletionTime = null, IsOptimizationCompleted = false, SpuOptimizationTaskId = spuOptimizationTask.Id }; insertSpuOptimizationBargainTeamTaskList.Add(spuOptimizationBargainTeamTask); #region 创建采购方案竞标任务 var waitJoinSchemeList = waitToCompetitiveTenderSchemeList.Where(ps => ps.BelongBargainTeamId == department.Id && qtskus.Contains(ps.SkuId)) .ToList(); //var waitJoinSchemeIdList = waitJoinSchemeList.Select(ps => ps.Id).ToList(); //var waitJonPurchaserList = waitToCompetitiveTenderSchemePurchaserList.Where(x => waitJoinSchemeIdList.Contains(x.SkuPurchaseSchemeId)); if (waitJoinSchemeList.Count() > 0) { insertSpuOptimizationCompetitiveTenderTaskList.AddRange(waitJoinSchemeList.Select(ps => new SpuOptimizationCompetitiveTenderTask() { Id = idGenerator.NewLong(), BargainTeamId = ps.BelongBargainTeamId, CreateTime = DateTime.Now, IsUpdateQuotedPrice = false, SchemeGroupId = ps.SchemeGroupId, SchemeId = ps.Id, SkuId = ps.SkuId, SpuOptimizationBargainTeamTaskId = spuOptimizationBargainTeamTask.Id, SpuOptimizationTaskId = spuOptimizationTask.Id, UpdateTime = DateTime.Now })); //insertSpuOptimizationPurchaserCompetitiveTenderTaskList.AddRange(waitJonPurchaserList.Select(x => //{ // var ps = waitJoinSchemeList.FirstOrDefault(ps => ps.Id == x.SkuPurchaseSchemeId); // return new SpuOptimizationPurchaserCompetitiveTenderTask() // { // Id = idGenerator.NewLong(), // BargainTeamId = ps.BelongBargainTeamId, // CreateTime = DateTime.Now, // UpdateTime = DateTime.Now, // IsUpdateQuotedPrice = false, // PurchaserId = x.PurchaserId, // SchemeGroupId = ps.SchemeGroupId, // SchemeId = ps.Id, // SkuId = ps.SkuId, // SpuOptimizationTaskId = spuOptimizationTask.Id // }; //})); } #endregion } #endregion #region 创建优化限时任务 { //判断sku是否首次采购 //var isFirst = !dbSpuTotalInfoList.Any(s => s.ProductId == productId); insertTimeLimitTaskList.Add(new TimeLimitTask() { Id = idGenerator.NewLong(), CreateTme = DateTime.Now, //ExpirationTime = DateTime.Now.AddDays(isFirst ? 2 : 1), ExpirationTime = timeLimitRules.CalculateExpirationTime(Enums.TimeLimitTaskType.待议价任务, DateTime.Now), //OrderId = o.OrderId, //OrderSn = o.OrderSn, ShopId = shopId, //SkuId = waitCheckOrderSku.SkuId, TaskType = Enums.TimeLimitTaskType.待议价任务, TaskId = spuOptimizationTask.Id, Remark = "首次采购限时任务" }); } #endregion } fsql.Transaction(() => { if (insertSpuOptimizationTaskList.Count() > 0) fsql.Insert(insertSpuOptimizationTaskList).ExecuteAffrows(); if (insertSkuOptimizationTaskList.Count() > 0) fsql.Insert(insertSkuOptimizationTaskList).ExecuteAffrows(); if (insertSpuOptimizationBargainTeamTaskList.Count() > 0) fsql.Insert(insertSpuOptimizationBargainTeamTaskList).ExecuteAffrows(); if (insertSpuOptimizationCompetitiveTenderTaskList.Count() > 0) fsql.Insert(insertSpuOptimizationCompetitiveTenderTaskList).ExecuteAffrows(); //if (insertSpuOptimizationPurchaserCompetitiveTenderTaskList.Count() > 0) // fsql.Insert(insertSpuOptimizationPurchaserCompetitiveTenderTaskList).ExecuteAffrows(); if (insertTimeLimitTaskList.Count() > 0) fsql.Insert(insertTimeLimitTaskList).ExecuteAffrows(); }); } /// /// 更新报价 /// /// /// public void BatchUpdateCompetitiveTenderQuotation(BatchUpdateCompetitiveTenderQuotationRequest request, string userId) { #region 获取用户和部门信息 var uInfo = userBusiness.GetisBargainTeamByUserId(userId, true); #endregion #region 业务验证 var spuOptimizationTask = fsql.Select(request.SpuOptimizationTaskId).ToOne(); if (spuOptimizationTask == null) throw new BusinessException($"待优化任务{request.SpuOptimizationTaskId}不存在"); var spuOptimizationBargainTeamTask = fsql.Select().Where(sbt => sbt.SpuOptimizationTaskId == request.SpuOptimizationTaskId && sbt.BelongTeamId == uInfo.bargainTeam.Id).ToOne(); if (spuOptimizationBargainTeamTask == null) throw new BusinessException($"待优化任务{request.SpuOptimizationTaskId}中不存在议价组{uInfo.bargainTeam.Id}/{uInfo.bargainTeam.DepartmentName}的子任务"); var skuIdList = fsql.Select().Where(s => s.SpuOptimizationTaskId == request.SpuOptimizationTaskId).ToList(s => s.SkuId); #endregion #region DBOperation List insertSpuOptimizationCompetitiveTenderTaskList = new List(); List updateCompetitiveTenderTaskIdList = new List(); List insertUpdatePriceList = new List(); #endregion //var skuList = request.ItemList.Select(x => x.SkuId).Distinct().ToList(); var purchaseSkuIdList = request.ItemList.Select(x => x.PurchaseSkuId).Distinct().ToList(); //查询竞标任务 var competitiveTenderTaskList = fsql.Select() .Where(ct => ct.BargainTeamId == uInfo.bargainTeam.Id && ct.SpuOptimizationTaskId == request.SpuOptimizationTaskId && ct.SchemeGroupId == request.SchemeGroupId) .ToList(); //查询配件关联的采购方案 var relationPurchaseSchemeIdList = fsql.Select() .Where(ps => ps.SchemeGroupId == request.SchemeGroupId && ps.BelongBargainTeamId == uInfo.bargainTeam.Id && fsql.Select() .Where(pss => skuIdList.Contains(pss.SkuId) && purchaseSkuIdList.Contains(pss.PurchaseSkuId) && pss.SkuPurchaseSchemeId == ps.Id).Any()) .ToList(ps => ps.Id); var relationPurchaseSchemeList = purchaseSchemeBusiness.GetPurchaseSchemeList(new QuerySchemeRequest() { SchemeIdList = relationPurchaseSchemeIdList, IncludePurchaseSkuBasicInfo = 0 }); //查询配件级报价任务 var updatePriceRecordList = fsql.Select() .Where(x => x.SpuOptimizationTaskId == request.SpuOptimizationTaskId && x.BargainTeamId == uInfo.bargainTeam.Id) .ToList(); //筛选出不在竞标任务中的采购方案 var noJoinCompetitiveTenderPurchaseSchemeList = relationPurchaseSchemeList.Where(ps => !competitiveTenderTaskList.Any(ct => ct.SchemeId == ps.Id)).ToList(); { var batchEditPurchaseSkuActualPriceRequest = request.Map(); batchEditPurchaseSkuActualPriceRequest.ProductId = spuOptimizationTask.ProductId; purchaseSchemeBusiness.BatchEditPurchaseSkuActualPrice(batchEditPurchaseSkuActualPriceRequest, uInfo); } insertUpdatePriceList.AddRange(request.ItemList.Where(x => !updatePriceRecordList.Any(r => r.PurchaseSkuId == x.PurchaseSkuId)).Select(x => new SpuOptimizationProductSkuUpdateQuotedPriceRecord() { Id = idGenerator.NewLong(), BargainTeamId = uInfo.bargainTeam.Id, CreateTime = DateTime.Now, PurchaseSkuId = x.PurchaseSkuId, SpuOptimizationTaskId = request.SpuOptimizationTaskId, UserId = uInfo.user.Id })); if (noJoinCompetitiveTenderPurchaseSchemeList.Count() > 0) { insertSpuOptimizationCompetitiveTenderTaskList.AddRange(noJoinCompetitiveTenderPurchaseSchemeList.Select(ps => new SpuOptimizationCompetitiveTenderTask() { Id = idGenerator.NewLong(), CreateTime = DateTime.Now, BargainTeamId = uInfo.bargainTeam.Id, IsUpdateQuotedPrice = true, SchemeGroupId = ps.SchemeGroupId, SchemeId = ps.Id, SkuId = ps.SkuId, SpuOptimizationBargainTeamTaskId = spuOptimizationBargainTeamTask.Id, SpuOptimizationTaskId = request.SpuOptimizationTaskId, UpdateTime = DateTime.Now })); } if (competitiveTenderTaskList.Count() > 0) { //updateCompetitiveTenderTaskIdList.AddRange(competitiveTenderTaskList.Select(ct => ct.Id).ToList()); foreach (var ctTask in competitiveTenderTaskList) { if (ctTask.IsUpdateQuotedPrice == true) continue; var scheme = relationPurchaseSchemeList.FirstOrDefault(ps => ps.Id == ctTask.SchemeId); if (scheme == null) continue; var pssList = scheme.PurchaseSchemeProductList.SelectMany(psp => psp.PurchaseSchemeProductSkuList); if (pssList.Any(pss => request.ItemList.Any(item => item.PurchaseSkuId == pss.PurchaseSkuId))) { //ctTask.IsUpdateQuotedPrice = true; updateCompetitiveTenderTaskIdList.Add(ctTask.Id); } } } fsql.Transaction(() => { if (insertSpuOptimizationCompetitiveTenderTaskList.Count() > 0) fsql.Insert(insertSpuOptimizationCompetitiveTenderTaskList).ExecuteAffrows(); if (updateCompetitiveTenderTaskIdList.Count() > 0) fsql.Update(updateCompetitiveTenderTaskIdList) .Set(ct => ct.IsUpdateQuotedPrice, true) .Set(ct => ct.UpdateTime, DateTime.Now) .ExecuteAffrows(); if (insertUpdatePriceList.Count() > 0) fsql.Insert(insertUpdatePriceList).ExecuteAffrows(); }); } /// /// 完成优化 /// /// /// /// public void CompleteOptimization(long taskId, string userId) { #region 获取用户和部门信息 var uInfo = userBusiness.GetisBargainTeamByUserId(userId, true); #endregion #region 业务验证 var spuOptimizationTask = fsql.Select(taskId).ToOne(); if (spuOptimizationTask == null) throw new BusinessException($"待优化任务{taskId}不存在"); if (spuOptimizationTask.IsOptimizationCompleted == true) throw new BusinessException("待优化任务已完成"); var spuOptimizationBargainTeamTaskList = fsql.Select() .Where(sbt => sbt.SpuOptimizationTaskId == taskId) .ToList(); var currentspuOptimizationBargainTeamTask = spuOptimizationBargainTeamTaskList.FirstOrDefault(sc => sc.BelongTeamId == uInfo.bargainTeam.Id); if (currentspuOptimizationBargainTeamTask == null) throw new BusinessException($"未找到议价组{uInfo.bargainTeam.DepartmentName}的议价子任务"); if (currentspuOptimizationBargainTeamTask.IsOptimizationCompleted == true) throw new BusinessException($"{uInfo.bargainTeam.DepartmentName}的议价子任务已完成"); var skuIdList = fsql.Select() .Where(s => s.SpuOptimizationTaskId == taskId) .ToList(s => s.SkuId); //查询全部竞标任务 var allBargainTeamCompetitiveTenderTaskList = fsql.Select() .Where(ct => ct.SpuOptimizationTaskId == taskId) .ToList(); //查询当前议价组的竞标任务 var currentBargainTeamCompetitiveTenderTaskList = allBargainTeamCompetitiveTenderTaskList.Where(ct => ct.BargainTeamId == uInfo.bargainTeam.Id).ToList(); if (currentBargainTeamCompetitiveTenderTaskList.Count() == 0) throw new BusinessException($"议价组{uInfo.bargainTeam.DepartmentName}没有参与竞标的采购方案,不能完成优化任务"); var currentBargainTeamCompetitiveTenderSchemeIdList = currentBargainTeamCompetitiveTenderTaskList.Select(ct => ct.SchemeId).ToList(); #region 验证该议价组的符合sku条件的采购方案是否都参与投标 var waitCheckPurchaseSchemeIdList = fsql.Select() .Where(ps => ps.BelongBargainTeamId == uInfo.bargainTeam.Id && skuIdList.Contains(ps.SkuId)) .ToList(ps => ps.Id); if (waitCheckPurchaseSchemeIdList.Count() == 0) throw new BusinessException($"议价组{uInfo.bargainTeam.DepartmentName}没有参与竞标的采购方案,不能完成优化任务"); var noJoinCompetitiveTenderSchemeIdList = waitCheckPurchaseSchemeIdList.Except(currentBargainTeamCompetitiveTenderSchemeIdList); if (noJoinCompetitiveTenderSchemeIdList.Count() > 0) throw new BusinessException($"议价组{uInfo.bargainTeam.DepartmentName}存在{noJoinCompetitiveTenderSchemeIdList.Count()}个符合条件但未参与竞标的采购方案"); #endregion #region 验证该议价组参与投标的采购方案是否都完成报价 if (currentBargainTeamCompetitiveTenderTaskList.Any(ct => ct.IsUpdateQuotedPrice == false)) throw new BusinessException($"议价组{uInfo.bargainTeam.DepartmentName}存在未更新报价的投标"); #endregion currentspuOptimizationBargainTeamTask.IsOptimizationCompleted = true; #endregion IUpdate updateBargainTask = null; IUpdate updateSpuTask = null; IUpdate updateSpuSaleInfo = null; IUpdate updateTimeLimitTask = null; IUpdate updateCompetitiveTenderTask = null; if (!spuOptimizationBargainTeamTaskList.Any(sc => sc.IsOptimizationCompleted == false)) { //全部完成 #region 更新spu销量表 var spuSaleInfo = fsql.Select(spuOptimizationTask.ProductId).ToOne(); if (spuSaleInfo == null) throw new BusinessException($"未找到spu{spuOptimizationTask.ProductId}销量"); updateSpuSaleInfo = fsql.Update(spuOptimizationTask.ProductId) .SetIf(spuSaleInfo.IsFirstPurchaseCompleted == false, s => s.IsFirstPurchaseCompleted, true) .SetIf(spuSaleInfo.IsFirstPurchaseCompleted == false, s => s.FirstPurchaseCompletedItemCount == s.ItemCount) .SetIf(spuSaleInfo.IsFirstPurchaseCompleted == true && spuSaleInfo.IsFirstOptimizationCompleted == false, s => s.IsFirstOptimizationCompleted, true) .SetIf(spuSaleInfo.IsFirstPurchaseCompleted == true && spuSaleInfo.IsFirstOptimizationCompleted == false, s => s.FirstOptimizationCompletedItemCount == s.ItemCount) .Set(s => s.LastOptimizationItemCount == s.ItemCount) .Set(s => s.LastOptimizationTime, DateTime.Now) .Set(s => s.UpdateTime, DateTime.Now); #endregion #region 更新待优化任务 updateSpuTask = fsql.Update(spuOptimizationTask.Id) .Set(t => t.IsOptimizationCompleted, true) .Set(t => t.CompletionTime, DateTime.Now); #endregion #region 更新待优化限时任务 updateTimeLimitTask = fsql.Update().Set(t => t.CompletionTime, DateTime.Now) .Set(t => t.IsTimely == (DateTime.Now < t.ExpirationTime ? true : false)) .Where(t => t.TaskId == spuOptimizationTask.Id && t.CompletionTime == null && t.TaskType == Enums.TimeLimitTaskType.待议价任务); #endregion #region 评选中标结果 var allBargainTeamCompetitiveTenderSchemeIdList = allBargainTeamCompetitiveTenderTaskList.Select(ct => ct.SchemeId).ToList(); var allBargainTeamPurchaseSchemeList = purchaseSchemeBusiness.GetPurchaseSchemeList(new QuerySchemeRequest() { SchemeIdList = allBargainTeamCompetitiveTenderSchemeIdList, IncludePurchaseSkuBasicInfo = 0 }); var victoryCompetitiveTenderTaskList = VictoryPlanSelection(allBargainTeamCompetitiveTenderTaskList, allBargainTeamPurchaseSchemeList); var victoryCompetitiveTenderTaskIdList = victoryCompetitiveTenderTaskList.Select(ct => ct.Id).ToList(); updateCompetitiveTenderTask = fsql.Update(victoryCompetitiveTenderTaskIdList) .Set(ct => ct.IsWin, true); #endregion } #region 更新待优化议价组任务 updateBargainTask = fsql.Update(currentspuOptimizationBargainTeamTask.Id) .Set(sc => sc.IsOptimizationCompleted, true) .Set(sc => sc.CompletionTime, DateTime.Now); #endregion fsql.Transaction(() => { updateSpuTask?.ExecuteAffrows(); updateBargainTask?.ExecuteAffrows(); updateSpuSaleInfo?.ExecuteAffrows(); updateTimeLimitTask?.ExecuteAffrows(); updateCompetitiveTenderTask?.ExecuteAffrows(); }); } /// /// 查询待优化任务 /// /// /// /// /// public ListResponse GetNoCompletionSkuOptimizationTask(QueryNoCompletionOptimizationTaskRequest request, string userId) { request.EndTime = request.EndTime.Date.AddDays(1).AddSeconds(-1); var uInfo = userBusiness.GetisBargainTeamByUserId(userId); ISelect select = null; if (request.SpuOptimizationTaskId != null && request.SpuOptimizationTaskId != 0) { select = fsql.Select(request.SpuOptimizationTaskId); } else { string spuKeyWords = string.Empty, skuKeyWords = string.Empty; if (!string.IsNullOrEmpty(request.SpuOrSku)) { if (Regex.IsMatch(request.SpuOrSku, @"^\d{2,10}$")) spuKeyWords = request.SpuOrSku; else if (Regex.IsMatch(request.SpuOrSku, @"^\w{2,20}$")) skuKeyWords = request.SpuOrSku; } var barginTeamId = uInfo.bargainTeam?.Id ?? string.Empty; select = fsql.Select() .Where(t => t.CreateTime >= request.StartTime && t.CreateTime <= request.EndTime) .WhereIf(request.BelongShopId != null && request.BelongShopId != 0, t => t.BelongShopId == request.BelongShopId) .WhereIf(!string.IsNullOrEmpty(request.JDSku) || !string.IsNullOrEmpty(skuKeyWords), t => fsql.Select() .Where(st => st.SpuOptimizationTaskId == t.Id) .WhereIf(!string.IsNullOrEmpty(request.JDSku), st => st.JDSkuId == request.JDSku) .WhereIf(!string.IsNullOrEmpty(skuKeyWords), st => st.SkuId == skuKeyWords) .Any()) .WhereIf(!string.IsNullOrEmpty(request.TitleKeywords), t => t.ProductTitle.Contains(request.TitleKeywords)) .WhereIf(!string.IsNullOrEmpty(spuKeyWords), t => t.ProductId == spuKeyWords); /* .WhereIf(request.IsCompleted, t => t.IsOptimizationCompleted == true || fsql.Select() .Where(sbt => sbt.IsOptimizationCompleted == true && sbt.SpuOptimizationTaskId == t.Id && sbt.BelongTeamId == barginTeamId) .Any()) .WhereIf(!request.IsCompleted && !string.IsNullOrEmpty(barginTeamId), t => t.IsOptimizationCompleted == false && fsql.Select() .Where(sbt => sbt.IsOptimizationCompleted == false && sbt.SpuOptimizationTaskId == t.Id && sbt.BelongTeamId == barginTeamId) .Any()) .WhereIf(!request.IsCompleted && string.IsNullOrEmpty(barginTeamId), t => t.IsOptimizationCompleted == false) */ if (request.State == 0) { if (string.IsNullOrEmpty(barginTeamId)) { //非议价组查询未完成 select = select.Where(t => t.IsOptimizationCompleted == false); } else { //议价组查询未完成 select = select.Where(t => t.IsOptimizationCompleted == false && fsql.Select() .Where(sbt => sbt.IsOptimizationCompleted == false && sbt.SpuOptimizationTaskId == t.Id && sbt.BelongTeamId == barginTeamId) .Any()); } } else if (request.State == 1) { if (string.IsNullOrEmpty(barginTeamId)) { //非议价组查询已完成 select = select.Where(t => t.IsOptimizationCompleted == true); } else { //议价组查询已完成 select = select.Where(t => fsql.Select() .Where(sbt => sbt.IsOptimizationCompleted == true && sbt.SpuOptimizationTaskId == t.Id && sbt.BelongTeamId == barginTeamId) .Any()); } } else if (request.State == 2) { //已超时 select = select.Where(t => t.IsOptimizationCompleted == true) .Where(t=> fsql.Select() .Where(sbt => sbt.IsOptimizationCompleted == false && sbt.SpuOptimizationTaskId == t.Id ) .WhereIf(!string.IsNullOrEmpty(barginTeamId),sbt=>sbt.BelongTeamId == barginTeamId) .Any()); } } var sql = select.ToSql(); var taskList = select.OrderBy(t => t.CreateTime) .Count(out var total) .Page(request.PageIndex, request.PageSize) .ToList(); if (taskList.Count() == 0) return new ListResponse() { TotalCount = 0, Items = null }; var spuTaskIdList = taskList.Select(t => t.Id).ToList(); #region 获取议价组任务 var bargainTeamTaskList = fsql.Select() .Where(sbt => spuTaskIdList.Contains(sbt.SpuOptimizationTaskId)) .ToList(); var bargainTeamIdList = bargainTeamTaskList.Select(x => x.BelongTeamId).Distinct().ToList(); #endregion #region 获取SKU优化任务 var skuTaskList = fsql.Select() .LeftJoin((st, ps) => st.SkuId == ps.Id) .Where((st, ps) => spuTaskIdList.Contains(st.SpuOptimizationTaskId)) .ToList((st, ps) => new SkuOptimizationTaskResponse { CreateTime = st.CreateTime, Id = st.Id, JDSkuId = st.JDSkuId, Logo = ps.Logo, PreItemCount = st.PreItemCount, PrePurchaseAmount = st.PrePurchaseAmount, SkuId = st.SkuId, SpuOptimizationTaskId = st.SpuOptimizationTaskId, SkuName = ps.SkuName, Price = ps.Price }); var skuIdList = skuTaskList.Select(st => st.SkuId).ToList(); #endregion #region 限时任务 var timelimitTaskList = fsql.Select() .Where(t => t.TaskType == Enums.TimeLimitTaskType.待议价任务 && spuTaskIdList.Contains(t.TaskId)) .ToList(); #endregion #region 获取采购方案 if (skuIdList.Count() == 0 && bargainTeamIdList.Count() == 0) return new ListResponse() { Items = null, TotalCount = 0 }; var purchaseSchemeList = purchaseSchemeBusiness.GetPurchaseSchemeList(new QuerySchemeRequest() { SkuIdList = skuIdList, BargainTeamIdList = bargainTeamIdList, IncludePurchaseSkuBasicInfo = 1, IncludePurchaseSkuStatisticsInfo = 1 }); #endregion #region 获取采购方案分组 var purchaseSchemeGroupIdList = purchaseSchemeList.Select(ps => ps.SchemeGroupId).Distinct().ToList(); var purchaseSchemeGroupList = fsql.Select(purchaseSchemeGroupIdList).ToList(); #endregion foreach (var task in taskList) { task.BargainTeamTaskList = bargainTeamTaskList.Where(sbt => sbt.SpuOptimizationTaskId == task.Id).ToList(); task.TimeLimitTask = timelimitTaskList.FirstOrDefault(t => t.TaskId == task.Id); if (task.TimeLimitTask != null) task.TimeLimitTask.RemainingTime = timeLimitRules.CalculateLessTimeForWorkHour(task.TimeLimitTask.ExpirationTime.Value); task.IsCompletedByCurrentTeam = task.BargainTeamTaskList.FirstOrDefault(sbt => sbt.BelongTeamId == uInfo.bargainTeam?.Id)?.IsOptimizationCompleted == true; task.SkuOptimizationTaskList = skuTaskList.Where(st => st.SpuOptimizationTaskId == task.Id).ToList(); #region 组装sku优化任务的采购方案信息 foreach (var skuTask in task.SkuOptimizationTaskList) { skuTask.RelationSchemeList = purchaseSchemeList.Where(ps => ps.SkuId == skuTask.SkuId) .Select(ps => new SkuOptimizationTaskPurchaseSchemeResponse() { SchemeId = ps.Id, SchemeGroupId = ps.SchemeGroupId, IsFreeFreight = ps.IsFreeFreight, LastPurchasePriceCost = ps.LastPurchasePriceCost, PurchaseSchemeCost = ps.BargainingCost ?? ps.DefaultCost }).ToList(); } #endregion #region 合并分组/采购商/配件 var currentTaskSkuIdList = task.SkuOptimizationTaskList.Select(st => st.SkuId).ToList(); var currentPurchaseSchemeGroups = purchaseSchemeList.Where(p => currentTaskSkuIdList.Contains(p.SkuId) && p.BelongBargainTeamId == uInfo.bargainTeam?.Id) .GroupBy(p => p.SchemeGroupId) .ToList(); task.MergePurchaseScemeGroupList = new List(); foreach (var schemeGroup in currentPurchaseSchemeGroups) { var mergeSchemeGroup = new MergePurchaseSchemeGroupResponse() { Id = schemeGroup.Key, GroupName = purchaseSchemeGroupList.FirstOrDefault(g => g.Id == schemeGroup.Key)?.GroupName }; task.MergePurchaseScemeGroupList.Add(mergeSchemeGroup); var schemeList = schemeGroup.ToList(); foreach (var scheme in schemeList) { foreach (var psp in scheme.PurchaseSchemeProductList) { var mergePurchaser = mergeSchemeGroup.PurchaserList.FirstOrDefault(p => p.Id == psp.PurchaserId); if (mergePurchaser == null) { mergePurchaser = scheme.PurchaserList.FirstOrDefault(p => p.Id == psp.PurchaserId)?.Map(); if (mergePurchaser == null) throw new BusinessException($"匹配采购商异常 schemeId {scheme.Id} pspProductId {psp.ProductId}"); mergeSchemeGroup.PurchaserList.Add(mergePurchaser); } foreach (var pss in psp.PurchaseSchemeProductSkuList) { var mergePss = mergePurchaser.MergePurchaseSchemeProductSkuList.FirstOrDefault(mpss => mpss.PurchaseSkuId == pss.PurchaseSkuId); if (mergePss == null) { mergePss = pss.Map(); mergePss.PurchaserId = mergePurchaser.Id; mergePss.BelongSkuIdList.Add(pss.SkuId); mergePss.PurchaseUrl = psp.PurchaseUrl; mergePurchaser.MergePurchaseSchemeProductSkuList.Add(mergePss); } else if (!mergePss.BelongSkuIdList.Contains(pss.SkuId)) mergePss.BelongSkuIdList.Add(pss.SkuId); } } } } #endregion } return new ListResponse() { Items = taskList, TotalCount = total }; } /// /// 评选结果 /// /// /// /// private IList VictoryPlanSelection(IList competitiveTenderTaskList, IList purchaseSchemeList) { var victoryList = new List(); var psGroups = purchaseSchemeList.GroupBy(ps => ps.SchemeGroupId); var winGroupKey = psGroups.Select(g => new { SchemeGroupId = g.Key, Cost = g.Sum(ps => ps.BargainingCost ?? ps.DefaultCost) }) .OrderByDescending(x => x.Cost) .FirstOrDefault(); victoryList.AddRange(competitiveTenderTaskList.Where(ct => ct.SchemeGroupId == winGroupKey.SchemeGroupId)); //foreach (var psGroup in psGroups) //{ // var psListOrderByCostDescList = psGroup.OrderByDescending(ps => ps.BargainingCost ?? ps.DefaultCost).ToList(); // var minCostScheme = psListOrderByCostDescList.FirstOrDefault(); // var competitiveTenderTask = competitiveTenderTaskList.FirstOrDefault(ct => ct.SchemeId == minCostScheme.Id); // victoryList.Add(competitiveTenderTask); //} return victoryList; } /// /// 限时任务超时回调 /// /// public void TimeLimitTaskTimeOutCallBack(long taskId) { try { var spuOptimizationTask = fsql.Select(taskId).ToOne(); if (spuOptimizationTask == null) throw new BusinessException($"待优化任务{taskId}不存在"); if (spuOptimizationTask.IsOptimizationCompleted == true) throw new BusinessException("待优化任务已完成"); IUpdate updateSpuTask = null; IUpdate updateSpuSaleInfo = null; IUpdate updateCompetitiveTenderTask = null; var spuOptimizationBargainTeamTaskList = fsql.Select() .Where(sbt => sbt.SpuOptimizationTaskId == taskId) .ToList(); if (spuOptimizationBargainTeamTaskList.Any(sc => sc.IsOptimizationCompleted == true)) { //任意一个议价组完成任务,该优化任务视为完成 var compleptionBargainTeamIdList = spuOptimizationBargainTeamTaskList.Where(sbt => sbt.IsOptimizationCompleted == true) .Select(sbt => sbt.BelongTeamId) .Distinct() .ToList(); //已完成议价任务的竞标任务 var compleptionBargainTeamCompetitiveTenderTaskList = fsql.Select() .Where(ct => ct.SpuOptimizationTaskId == taskId && compleptionBargainTeamIdList.Contains(ct.BargainTeamId)) .ToList(); #region 更新spu销量表 var spuSaleInfo = fsql.Select(spuOptimizationTask.ProductId).ToOne(); if (spuSaleInfo == null) throw new BusinessException($"未找到spu{spuOptimizationTask.ProductId}销量"); updateSpuSaleInfo = fsql.Update(spuOptimizationTask.ProductId) .SetIf(spuSaleInfo.IsFirstPurchaseCompleted == false, s => s.IsFirstPurchaseCompleted, true) .SetIf(spuSaleInfo.IsFirstPurchaseCompleted == false, s => s.FirstPurchaseCompletedItemCount == s.ItemCount) .SetIf(spuSaleInfo.IsFirstPurchaseCompleted == true && spuSaleInfo.IsFirstOptimizationCompleted == false, s => s.IsFirstOptimizationCompleted, true) .SetIf(spuSaleInfo.IsFirstPurchaseCompleted == true && spuSaleInfo.IsFirstOptimizationCompleted == false, s => s.FirstOptimizationCompletedItemCount == s.ItemCount) .Set(s => s.LastOptimizationItemCount == s.ItemCount) .Set(s => s.LastOptimizationTime, DateTime.Now) .Set(s => s.UpdateTime, DateTime.Now); #endregion #region 更新待优化任务 updateSpuTask = fsql.Update(spuOptimizationTask.Id) .Set(t => t.IsOptimizationCompleted, true) .Set(t => t.CompletionTime, DateTime.Now); #endregion #region 评选竞标结果 var compleptionBargainTeamPurchaseSchemeIdList = compleptionBargainTeamCompetitiveTenderTaskList.Select(ct => ct.SchemeId).ToList(); var compleptionBargainTeamPurchaseSchemeList = purchaseSchemeBusiness.GetPurchaseSchemeList(new QuerySchemeRequest() { SchemeIdList = compleptionBargainTeamPurchaseSchemeIdList, IncludePurchaseSkuBasicInfo = 0 }); var victoryCompetitiveTenderTaskList = VictoryPlanSelection(compleptionBargainTeamCompetitiveTenderTaskList, compleptionBargainTeamPurchaseSchemeList); var victoryCompetitiveTenderTaskIdList = victoryCompetitiveTenderTaskList.Select(ct => ct.Id).ToList(); updateCompetitiveTenderTask = fsql.Update(victoryCompetitiveTenderTaskIdList) .Set(ct => ct.IsWin, true); #endregion } fsql.Transaction(() => { updateSpuTask?.ExecuteAffrows(); updateSpuSaleInfo?.ExecuteAffrows(); updateCompetitiveTenderTask?.ExecuteAffrows(); }); } catch (Exception ex) { nLogManager.Default().Error(ex, "限时任务超时回调失败"); } } /// /// 从优化任务模块删除采购方案分组(级联删除采购分组下的其他) /// /// public void DeleteSchemeGroup(DeleteSchemeGroupFromSpuOptimizationTaskRequest request, string userId) { _ = userBusiness.GetisBargainTeamByUserId(userId, true); var schemeIdList = fsql.Select().Where(ps => ps.SchemeGroupId == request.SchemeGroupId).ToList(ps => ps.Id); fsql.Transaction(() => { fsql.Delete(request.SchemeGroupId).ExecuteAffrows(); if (schemeIdList.Count() > 0) { fsql.Delete(schemeIdList).ExecuteAffrows(); fsql.Delete().Where(psp => schemeIdList.Contains(psp.SkuPurchaseSchemeId)).ExecuteAffrows(); fsql.Delete().Where(pss => schemeIdList.Contains(pss.SkuPurchaseSchemeId)).ExecuteAffrows(); } fsql.Delete() .Where(ct => ct.SchemeGroupId == request.SchemeGroupId && ct.SpuOptimizationTaskId == request.SpuOptimizationId) .ExecuteAffrows(); }); //var competitiveTenderTaskList = fsql.Select() // .Where(ct => ct.SpuOptimizationTaskId == request.SpuOptimizationId && // ct.SchemeGroupId == request.SchemeGroupId) // .ToList(); //var schemeIdList = competitiveTenderTaskList.Select(ct => ct.SchemeId).ToList(); //purchaseSchemeBusiness.DeletePurchaseScheme(schemeIdList); //var ctTaskIdList = competitiveTenderTaskList.Select(ct => ct.Id); //fsql.Delete(ctTaskIdList).ExecuteAffrows(); } public long GetNoCompletedSpuOptimizationTaskCount(string userId) { var uInfo = userBusiness.GetisBargainTeamByUserId(userId); if (uInfo.isBargainTeam) { var barginTeamId = uInfo.bargainTeam?.Id ?? string.Empty; return fsql.Select().Where(t => t.IsOptimizationCompleted == false && fsql.Select() .Where(sbt => sbt.IsOptimizationCompleted == false && sbt.SpuOptimizationTaskId == t.Id && sbt.BelongTeamId == barginTeamId) .Any()).Count(); } return fsql.Select().Where(t => t.IsOptimizationCompleted == false).Count(); } } }