From 8abf75fa88d0cbeb395af8aeb0385646c7c59ce3 Mon Sep 17 00:00:00 2001 From: shanj <18996038927@163.com> Date: Mon, 12 Dec 2022 06:17:25 +0800 Subject: [PATCH] =?UTF-8?q?GOI=E9=A2=84=E8=AD=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BBWY.Server.Business/DingDingBusiness.cs | 66 +++ .../JD/JDStockNumWarningBusiness.cs | 65 +-- .../SiNan/GOIWarningBusiness.cs | 541 +++++++++++++++++- .../JDReportFormStatisticsBusiness.cs | 132 +++-- BBWY.Server.Business/TaskSchedulerManager.cs | 3 + BBWY.Server.Business/Vender/VenderBusiness.cs | 3 +- .../Dto/Request/Statistics/GOIRequest.cs | 2 + BBWY.Server.Model/Enums.cs | 12 + 8 files changed, 725 insertions(+), 99 deletions(-) create mode 100644 BBWY.Server.Business/DingDingBusiness.cs diff --git a/BBWY.Server.Business/DingDingBusiness.cs b/BBWY.Server.Business/DingDingBusiness.cs new file mode 100644 index 00000000..91c2a184 --- /dev/null +++ b/BBWY.Server.Business/DingDingBusiness.cs @@ -0,0 +1,66 @@ +using BBWY.Common.Extensions; +using BBWY.Common.Http; +using BBWY.Common.Models; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Security.Cryptography; +using System.Text; +using Yitter.IdGenerator; + +namespace BBWY.Server.Business +{ + public class DingDingBusiness : BaseBusiness, IDenpendency + { + private RestApiService restApiService; + + public DingDingBusiness(IFreeSql fsql, NLogManager nLogManager, IIdGenerator idGenerator, RestApiService restApiService) : base(fsql, nLogManager, idGenerator) + { + this.restApiService = restApiService; + } + + public void SendDingDingBotMessage(string secret, string webHook, string content) + { + var timestamp = DateTime.Now.DateTimeToStamp(); + var stringToSign = timestamp + "\n" + secret; + var sign = EncryptWithSHA256(stringToSign, secret); + var url = $"{webHook}×tamp={timestamp}&sign={sign}"; + var result = restApiService.SendRequest(url, string.Empty, new + { + msgtype = "text", + text = new + { + content = content + } + }, null, HttpMethod.Post); + if (result.StatusCode != System.Net.HttpStatusCode.OK) + throw new Exception($"发送钉钉机器人消息失败 {result.Content}"); + } + + /// + /// Base64 SHA256 + /// + /// 待加密数据 + /// 密钥 + /// + private string EncryptWithSHA256(string data, string secret) + { + secret = secret ?? ""; + + // 1、string 转换成 utf-8 的byte[] + var encoding = Encoding.UTF8; + byte[] keyByte = encoding.GetBytes(secret); + byte[] dataBytes = encoding.GetBytes(data); + + // 2、 HMACSHA256加密 + using (var hmac256 = new HMACSHA256(keyByte)) + { + byte[] hashData = hmac256.ComputeHash(dataBytes); + // 3、转换成base64 + var base64Str = Convert.ToBase64String(hashData); + // 4、urlEncode编码 + return System.Web.HttpUtility.UrlEncode(base64Str, Encoding.UTF8); + } + } + } +} diff --git a/BBWY.Server.Business/EarlyWarning/JD/JDStockNumWarningBusiness.cs b/BBWY.Server.Business/EarlyWarning/JD/JDStockNumWarningBusiness.cs index 522a9dea..2805b920 100644 --- a/BBWY.Server.Business/EarlyWarning/JD/JDStockNumWarningBusiness.cs +++ b/BBWY.Server.Business/EarlyWarning/JD/JDStockNumWarningBusiness.cs @@ -22,14 +22,16 @@ namespace BBWY.Server.Business public class JDStockNumWarningBusiness : BaseSyncBusiness, IDenpendency { private IList validStorageTypeList; + private DingDingBusiness dingDingBusiness; - public JDStockNumWarningBusiness(RestApiService restApiService, IOptions options, NLogManager nLogManager, IFreeSql fsql, IIdGenerator idGenerator, TaskSchedulerManager taskSchedulerManager, VenderBusiness venderBusiness, YunDingBusiness yunDingBusiness) : base(restApiService, options, nLogManager, fsql, idGenerator, taskSchedulerManager, venderBusiness, yunDingBusiness) + public JDStockNumWarningBusiness(RestApiService restApiService, IOptions options, NLogManager nLogManager, IFreeSql fsql, IIdGenerator idGenerator, TaskSchedulerManager taskSchedulerManager, VenderBusiness venderBusiness, YunDingBusiness yunDingBusiness, DingDingBusiness dingDingBusiness) : base(restApiService, options, nLogManager, fsql, idGenerator, taskSchedulerManager, venderBusiness, yunDingBusiness) { validStorageTypeList = new List() { Enums.StorageType.云仓, Enums.StorageType.京仓, Enums.StorageType.本地自发 }; + this.dingDingBusiness = dingDingBusiness; } public void StartCheckStockNum() @@ -44,9 +46,9 @@ namespace BBWY.Server.Business private void CheckStockNum(ShopResponse shop, IList storeHouseList) { + var loggerName = $"库存预警-{shop.ShopName}"; try { - var loggerName = $"库存预警-{shop.ShopName}"; long shopId = long.Parse(shop.ShopId); var yesterDayDate = DateTime.Now.Date.AddDays(-1); var ysterDayTime = DateTime.Now.Date.AddSeconds(-1); @@ -262,52 +264,27 @@ namespace BBWY.Server.Business if (isSendDingTalk) { - var secret = shop.DingDingKey; - var timestamp = DateTime.Now.DateTimeToStamp(); - var stringToSign = timestamp + "\n" + secret; - var sign = EncryptWithSHA256(stringToSign, secret); - var url = $"{shop.DingDingWebHook}×tamp={timestamp}&sign={sign}"; - var result = restApiService.SendRequest(url, string.Empty, new - { - msgtype = "text", - text = new - { - content = dingdingContentBuilder.ToString() - } - }, null, HttpMethod.Post); - if (result.StatusCode != System.Net.HttpStatusCode.OK) - throw new Exception($"{shop.ShopName} 发送钉钉库存预警失败 {result.Content}"); + dingDingBusiness.SendDingDingBotMessage(shop.DingDingKey, shop.DingDingWebHook, dingdingContentBuilder.ToString()); + //var secret = shop.DingDingKey; + //var timestamp = DateTime.Now.DateTimeToStamp(); + //var stringToSign = timestamp + "\n" + secret; + //var sign = EncryptWithSHA256(stringToSign, secret); + //var url = $"{shop.DingDingWebHook}×tamp={timestamp}&sign={sign}"; + //var result = restApiService.SendRequest(url, string.Empty, new + //{ + // msgtype = "text", + // text = new + // { + // content = dingdingContentBuilder.ToString() + // } + //}, null, HttpMethod.Post); + //if (result.StatusCode != System.Net.HttpStatusCode.OK) + // throw new Exception($"{shop.ShopName} 发送钉钉库存预警失败 {result.Content}"); } } catch (Exception ex) { - nLogManager.GetLogger($"库存预警-{shop.ShopName}").Error(ex, "查询sku库存失败"); - } - } - - /// - /// Base64 SHA256 - /// - /// 待加密数据 - /// 密钥 - /// - private string EncryptWithSHA256(string data, string secret) - { - secret = secret ?? ""; - - // 1、string 转换成 utf-8 的byte[] - var encoding = Encoding.UTF8; - byte[] keyByte = encoding.GetBytes(secret); - byte[] dataBytes = encoding.GetBytes(data); - - // 2、 HMACSHA256加密 - using (var hmac256 = new HMACSHA256(keyByte)) - { - byte[] hashData = hmac256.ComputeHash(dataBytes); - // 3、转换成base64 - var base64Str = Convert.ToBase64String(hashData); - // 4、urlEncode编码 - return System.Web.HttpUtility.UrlEncode(base64Str, Encoding.UTF8); + nLogManager.GetLogger(loggerName).Error(ex, "查询sku库存失败"); } } } diff --git a/BBWY.Server.Business/SiNan/GOIWarningBusiness.cs b/BBWY.Server.Business/SiNan/GOIWarningBusiness.cs index 7ea794fc..a3e4ace9 100644 --- a/BBWY.Server.Business/SiNan/GOIWarningBusiness.cs +++ b/BBWY.Server.Business/SiNan/GOIWarningBusiness.cs @@ -1,12 +1,549 @@ -using BBWY.Common.Models; +using BBWY.Common.Extensions; +using BBWY.Common.Http; +using BBWY.Common.Models; +using BBWY.Server.Business.Statistics; +using BBWY.Server.Model; +using BBWY.Server.Model.Db; +using BBWY.Server.Model.Dto; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading; +using System.Threading.Tasks; using Yitter.IdGenerator; namespace BBWY.Server.Business.SiNan { public class GOIWarningBusiness : BaseBusiness, IDenpendency { - public GOIWarningBusiness(IFreeSql fsql, NLogManager nLogManager, IIdGenerator idGenerator) : base(fsql, nLogManager, idGenerator) + private TaskSchedulerManager taskSchedulerManager; + private VenderBusiness venderBusiness; + private JDReportFormStatisticsBusiness jDReportFormStatisticsBusiness; + private DingDingBusiness dingDingBusiness; + + public GOIWarningBusiness(IFreeSql fsql, NLogManager nLogManager, IIdGenerator idGenerator, TaskSchedulerManager taskSchedulerManager, VenderBusiness venderBusiness, JDReportFormStatisticsBusiness jDReportFormStatisticsBusiness, DingDingBusiness dingDingBusiness) : base(fsql, nLogManager, idGenerator) + { + this.taskSchedulerManager = taskSchedulerManager; + this.venderBusiness = venderBusiness; + this.jDReportFormStatisticsBusiness = jDReportFormStatisticsBusiness; + this.dingDingBusiness = dingDingBusiness; + } + + public void StartCheckGOI() + { + var shopList = venderBusiness.GetShopList(platform: Enums.Platform.京东, filterSiNan: true); + foreach (var shop in shopList) + { + Task.Factory.StartNew(() => CheckGOI(shop), CancellationToken.None, TaskCreationOptions.LongRunning, taskSchedulerManager.GOIWarningTaskScheduler); + } + } + + public void CheckGOI(ShopResponse shop) { + var loggerName = $"GOI预警-{shop.ShopName}"; + try + { + var shopId = long.Parse(shop.ShopId); + var yesterday = DateTime.Now.Date.AddDays(-1); + var startQueryDay = yesterday.AddDays(-6); + + var yesterdayJDpopularizeadskuList = fsql.Select() + .LeftJoin((s, c, adg) => s.CampaignId == c.CampaignId && s.Date == c.Date) + .LeftJoin((s, c, adg) => s.AdGroupId == adg.AdGroupId && s.Date == adg.Date) + .Where((s, c, adg) => s.ShopId == shopId && s.Date == yesterday) + .ToList((s, c, adg) => new + { + CampaignId = s.CampaignId, + CampaignName = c.CampaignName, + AdGroupId = s.AdGroupId, + AdGroupName = adg.AdGroupName, + AdId = s.AdId, + AdName = s.AdName, + BusinessType = s.BusinessType, + Sku = s.Sku + }); + + var adGroupIds = yesterdayJDpopularizeadskuList.Where(s => s.BusinessType == 2).Select(s => s.AdGroupId.Value).Distinct().ToList(); + var adIds = yesterdayJDpopularizeadskuList.Where(s => s.BusinessType == 2).Select(s => s.AdId.Value).Distinct().ToList(); + var skuIds = yesterdayJDpopularizeadskuList.Where(s => s.BusinessType == 134217728).Select(s => s.Sku).Distinct().ToList(); + + + bool isSendDingTalk = false; + var dingdingContentBuilder = new StringBuilder(); + dingdingContentBuilder.Append(shop.ShopName); + dingdingContentBuilder.AppendLine(); + + var growupCost = 0; //成长加速期花费阈值 + var growupLevel1Cost = 0; //成长加速期第一阶段成本 + var growupLevel2Cost = 0; //成长加速期第二阶段成本 + var growupLevel2MinGOI = 0M; //成长加速器第二阶段最低GOI + var growupLevel2MaxGOI = 0M; //成长加速器第二阶段最大GOI + var growupLevel3Cost = 0; //成长加速期第三阶段成本 + var growupLevel3MinGOI = 0M; //成长加速器第三阶段最低GOI + var growupLevel3MaxGOI = 0M; //成长加速器第三阶段最大GOI + var growupLevel4Cost = 0; //成长加速期第四阶段成本 + var growupLevel4MinGOI = 0M; //成长加速器第四阶段最低GOI + var growupLevel4MaxGOI = 0M; //成长加速器第四阶段最大GOI + + var matureCost = 0; //成熟期花费阈值 + var mature7dCost = 0; //成熟期7天花费阈值 + var matureLevel1MinGOI = 0M; //成熟期第一阶段最低GOI + var matureLevel1MaxGOI = 0M; //成熟期第一阶段最大GOI + + var stableCost = 0; //稳定期花费阈值 + var stable7dCost = 0; //稳定期7天花费阈值 + var stableLevel1MinGOI = 0M; //稳定期第一阶段最低GOI + var stableLevel1MaxGOI = 0M; //稳定期第一阶段最大GOI + + + if (shop.SiNanPolicyLevel == 0) //初级策略 + { + growupCost = 300; + growupLevel1Cost = 100; + growupLevel2Cost = 100; + growupLevel2MinGOI = 0.5M; + growupLevel2MaxGOI = 1.1M; + growupLevel3Cost = 200; + growupLevel3MinGOI = 0.7M; + growupLevel3MaxGOI = 1.1M; + growupLevel4Cost = 300; + growupLevel4MinGOI = 0.9M; + growupLevel4MaxGOI = 1.1M; + + matureCost = 300; + mature7dCost = 150; + matureLevel1MinGOI = 0.9M; + matureLevel1MaxGOI = 1.2M; + + stableCost = 300; + stable7dCost = 150; + stableLevel1MinGOI = 1.0M; + stableLevel1MaxGOI = 2; + } + else if (shop.SiNanPolicyLevel == 1) //中级策略 + { + growupCost = 600; + growupLevel1Cost = 200; + growupLevel2Cost = 200; + growupLevel2MinGOI = 0.5M; + growupLevel2MaxGOI = 1.1M; + growupLevel3Cost = 400; + growupLevel3MinGOI = 0.7M; + growupLevel3MaxGOI = 1.1M; + growupLevel4Cost = 600; + growupLevel4MinGOI = 0.9M; + growupLevel4MaxGOI = 1.1M; + + matureCost = 600; + mature7dCost = 300; + matureLevel1MinGOI = 0.9M; + matureLevel1MaxGOI = 1.2M; + + stableCost = 600; + stable7dCost = 300; + stableLevel1MinGOI = 1.0M; + stableLevel1MaxGOI = 2; + } + else if (shop.SiNanPolicyLevel == 2) //高级策略 + { + growupCost = 1000; + growupLevel1Cost = 300; + growupLevel2Cost = 300; + growupLevel2MinGOI = 0.5M; + growupLevel2MaxGOI = 1.1M; + growupLevel3Cost = 700; + growupLevel3MinGOI = 0.7M; + growupLevel3MaxGOI = 1.1M; + growupLevel4Cost = 999; + growupLevel4MinGOI = 0.9M; + growupLevel4MaxGOI = 1.1M; + + matureCost = 1000; + mature7dCost = 500; + matureLevel1MinGOI = 0.9M; + matureLevel1MaxGOI = 1.2M; + + stableCost = 1000; + stable7dCost = 500; + stableLevel1MinGOI = 1.0M; + stableLevel1MaxGOI = 2; + } + + #region 单元 + bool isAddBusinessTypeTitle = false; + var adGroupGOIList = jDReportFormStatisticsBusiness.CalculationAdGroupLevelGOI(new GOIRequest() + { + BusinessType = 2, + LevelIdList = adGroupIds, + OnlyCustomDate = true, + StartDate = yesterday, + EndDate = startQueryDay + }); + + foreach (var adGroupGOI in adGroupGOIList) + { + var adGroup = yesterdayJDpopularizeadskuList.FirstOrDefault(s => s.AdGroupId == adGroupGOI.LevelId); + if (adGroup == null) + continue; + + var logContentBuilder = new StringBuilder(); + logContentBuilder.AppendLine($"单元维度 {adGroup.CampaignName}({adGroup.CampaignId})-{adGroup.AdGroupName}({adGroup.AdGroupId})"); + + Enums.SiNanCycleType? siNanCycleType = Enums.SiNanCycleType.暂无周期; + bool isWarning = false; + string dingdingWarningContent = string.Empty; + + if (adGroupGOI.TotalCost < growupCost) + { + siNanCycleType = Enums.SiNanCycleType.成长加速期; + if (adGroupGOI.TotalCost < growupLevel1Cost) + { + //不建议调整 + isWarning = false; + } + else if (adGroupGOI.TotalCost >= growupLevel4Cost) + { + if (adGroupGOI.CustomDaysGOI.GOI < growupLevel4MinGOI) + { + isWarning = true; + dingdingWarningContent = $"{adGroup.CampaignName}-{adGroup.AdGroupName} 处于{siNanCycleType},近7天GOI低于{growupLevel4MinGOI},请及时优化!"; + } + else if (adGroupGOI.CustomDaysGOI.GOI > growupLevel4MaxGOI) + { + isWarning = true; + dingdingWarningContent = $"{adGroup.CampaignName}-{adGroup.AdGroupName} 处于{siNanCycleType},近7天GOI低于{growupLevel4MaxGOI},舍不得孩子套不住狼,请及时优化!"; + } + } + else if (adGroupGOI.TotalCost >= growupLevel3Cost) + { + if (adGroupGOI.CustomDaysGOI.GOI < growupLevel3MinGOI) + { + isWarning = true; + dingdingWarningContent = $"{adGroup.CampaignName}-{adGroup.AdGroupName} 处于{siNanCycleType},近7天GOI低于{growupLevel3MinGOI},请及时优化!"; + } + else if (adGroupGOI.CustomDaysGOI.GOI < growupLevel3MaxGOI) + { + isWarning = true; + dingdingWarningContent = $"{adGroup.CampaignName}-{adGroup.AdGroupName} 处于{siNanCycleType},近7天GOI低于{growupLevel3MaxGOI},舍不得孩子套不住狼,请及时优化!"; + } + } + else if (adGroupGOI.TotalCost >= growupLevel2Cost) + { + if (adGroupGOI.CustomDaysGOI.GOI < growupLevel2MinGOI) + { + isWarning = true; + dingdingWarningContent = $"{adGroup.CampaignName}-{adGroup.AdGroupName} 处于{siNanCycleType},近7天GOI低于{growupLevel2MinGOI},请及时优化!"; + } + else if (adGroupGOI.CustomDaysGOI.GOI < growupLevel2MaxGOI) + { + isWarning = true; + dingdingWarningContent = $"{adGroup.CampaignName}-{adGroup.AdGroupName} 处于{siNanCycleType},近7天GOI低于{growupLevel2MaxGOI},舍不得孩子套不住狼,请及时优化!"; + } + } + } + else if (adGroupGOI.TotalCost > matureCost && adGroupGOI.CustomDaysGOI.Cost > mature7dCost) + { + siNanCycleType = Enums.SiNanCycleType.成熟利润期; + if (adGroupGOI.CustomDaysGOI.GOI < matureLevel1MinGOI) + { + isWarning = true; + dingdingWarningContent = $"{adGroup.CampaignName}-{adGroup.AdGroupName} 处于{siNanCycleType},近7天GOI低于{matureLevel1MinGOI},请及时优化!"; + } + else if (adGroupGOI.CustomDaysGOI.GOI > matureLevel1MaxGOI) + { + isWarning = true; + dingdingWarningContent = $"{adGroup.CampaignName}-{adGroup.AdGroupName} 处于{siNanCycleType},近7天GOI低于{matureLevel1MaxGOI},舍不得孩子套不住狼,请及时优化!"; + } + } + else if (adGroupGOI.TotalCost > stableCost && adGroupGOI.CustomDaysGOI.Cost < stable7dCost) + { + siNanCycleType = Enums.SiNanCycleType.稳定日销期; + if (adGroupGOI.CustomDaysGOI.GOI < stableLevel1MinGOI) + { + isWarning = true; + dingdingWarningContent = $"{adGroup.CampaignName}-{adGroup.AdGroupName} 处于{siNanCycleType},近7天GOI低于{stableLevel1MinGOI},请及时优化!"; + } + else if (adGroupGOI.CustomDaysGOI.GOI > stableLevel1MaxGOI) + { + isWarning = true; + dingdingWarningContent = $"{adGroup.CampaignName}-{adGroup.AdGroupName} 处于{siNanCycleType},近7天GOI低于{stableLevel1MaxGOI},舍不得孩子套不住狼,请及时优化!"; + } + } + + logContentBuilder.AppendLine($"{siNanCycleType}"); + logContentBuilder.AppendLine($"累计推广花费{adGroupGOI.TotalCost}"); + logContentBuilder.AppendLine($"近7天花费{adGroupGOI.CustomDaysGOI.Cost}"); + logContentBuilder.AppendLine($"近7天GOI{adGroupGOI.CustomDaysGOI.GOI}"); + logContentBuilder.AppendLine($"是否出发预警{isWarning}"); + + if (isWarning) + { + isSendDingTalk = true; + if (!isAddBusinessTypeTitle) + { + dingdingContentBuilder.Append("快车业务线-单元维度\n"); + isAddBusinessTypeTitle = true; + } + + dingdingContentBuilder.Append($"{dingdingWarningContent}\n"); + } + } + #endregion + + #region 创意 + isAddBusinessTypeTitle = false; + + var adGOIList = jDReportFormStatisticsBusiness.CalculationAdLevelGOI(new GOIRequest() + { + BusinessType = 2, + LevelIdList = adIds, + OnlyCustomDate = true, + StartDate = yesterday, + EndDate = startQueryDay + }); + + foreach (var adGOI in adGOIList) + { + var ad = yesterdayJDpopularizeadskuList.FirstOrDefault(s => s.AdId == adGOI.LevelId); + if (ad == null) + continue; + + var logContentBuilder = new StringBuilder(); + logContentBuilder.AppendLine($"创意维度 {ad.CampaignName}({ad.CampaignId})-{ad.AdGroupName}({ad.AdGroupId})-{ad.AdName}({ad.AdId})"); + + Enums.SiNanCycleType? siNanCycleType = Enums.SiNanCycleType.暂无周期; + bool isWarning = false; + string dingdingWarningContent = string.Empty; + + if (adGOI.TotalCost < growupCost) + { + siNanCycleType = Enums.SiNanCycleType.成长加速期; + if (adGOI.TotalCost < growupLevel1Cost) + { + //不建议调整 + isWarning = false; + } + else if (adGOI.TotalCost >= growupLevel4Cost) + { + if (adGOI.CustomDaysGOI.GOI < growupLevel4MinGOI) + { + isWarning = true; + dingdingWarningContent = $"{ad.CampaignName}-{ad.AdGroupName}-{ad.AdName} 处于{siNanCycleType},近7天GOI低于{growupLevel4MinGOI},请及时优化!"; + } + else if (adGOI.CustomDaysGOI.GOI > growupLevel4MaxGOI) + { + isWarning = true; + dingdingWarningContent = $"{ad.CampaignName}-{ad.AdGroupName}-{ad.AdName} 处于{siNanCycleType},近7天GOI低于{growupLevel4MaxGOI},舍不得孩子套不住狼,请及时优化!"; + } + } + else if (adGOI.TotalCost >= growupLevel3Cost) + { + if (adGOI.CustomDaysGOI.GOI < growupLevel3MinGOI) + { + isWarning = true; + dingdingWarningContent = $"{ad.CampaignName}-{ad.AdGroupName}-{ad.AdName} 处于{siNanCycleType},近7天GOI低于{growupLevel3MinGOI},请及时优化!"; + } + else if (adGOI.CustomDaysGOI.GOI < growupLevel3MaxGOI) + { + isWarning = true; + dingdingWarningContent = $"{ad.CampaignName}-{ad.AdGroupName}-{ad.AdName} 处于{siNanCycleType},近7天GOI低于{growupLevel3MaxGOI},舍不得孩子套不住狼,请及时优化!"; + } + } + else if (adGOI.TotalCost >= growupLevel2Cost) + { + if (adGOI.CustomDaysGOI.GOI < growupLevel2MinGOI) + { + isWarning = true; + dingdingWarningContent = $"{ad.CampaignName}-{ad.AdGroupName}-{ad.AdName} 处于{siNanCycleType},近7天GOI低于{growupLevel2MinGOI},请及时优化!"; + } + else if (adGOI.CustomDaysGOI.GOI < growupLevel2MaxGOI) + { + isWarning = true; + dingdingWarningContent = $"{ad.CampaignName}-{ad.AdGroupName}-{ad.AdName} 处于{siNanCycleType},近7天GOI低于{growupLevel2MaxGOI},舍不得孩子套不住狼,请及时优化!"; + } + } + } + else if (adGOI.TotalCost > matureCost && adGOI.CustomDaysGOI.Cost > mature7dCost) + { + siNanCycleType = Enums.SiNanCycleType.成熟利润期; + if (adGOI.CustomDaysGOI.GOI < matureLevel1MinGOI) + { + isWarning = true; + dingdingWarningContent = $"{ad.CampaignName}-{ad.AdGroupName}-{ad.AdName} 处于{siNanCycleType},近7天GOI低于{matureLevel1MinGOI},请及时优化!"; + } + else if (adGOI.CustomDaysGOI.GOI > matureLevel1MaxGOI) + { + isWarning = true; + dingdingWarningContent = $"{ad.CampaignName}-{ad.AdGroupName}-{ad.AdName} 处于{siNanCycleType},近7天GOI低于{matureLevel1MaxGOI},舍不得孩子套不住狼,请及时优化!"; + } + } + else if (adGOI.TotalCost > stableCost && adGOI.CustomDaysGOI.Cost < stable7dCost) + { + siNanCycleType = Enums.SiNanCycleType.稳定日销期; + if (adGOI.CustomDaysGOI.GOI < stableLevel1MinGOI) + { + isWarning = true; + dingdingWarningContent = $"{ad.CampaignName}-{ad.AdGroupName}-{ad.AdName} 处于{siNanCycleType},近7天GOI低于{stableLevel1MinGOI},请及时优化!"; + } + else if (adGOI.CustomDaysGOI.GOI > stableLevel1MaxGOI) + { + isWarning = true; + dingdingWarningContent = $"{ad.CampaignName}-{ad.AdGroupName}-{ad.AdName} 处于{siNanCycleType},近7天GOI低于{stableLevel1MaxGOI},舍不得孩子套不住狼,请及时优化!"; + } + } + + logContentBuilder.AppendLine($"{siNanCycleType}"); + logContentBuilder.AppendLine($"累计推广花费{adGOI.TotalCost}"); + logContentBuilder.AppendLine($"近7天花费{adGOI.CustomDaysGOI.Cost}"); + logContentBuilder.AppendLine($"近7天GOI{adGOI.CustomDaysGOI.GOI}"); + logContentBuilder.AppendLine($"是否出发预警{isWarning}"); + + if (isWarning) + { + isSendDingTalk = true; + if (!isAddBusinessTypeTitle) + { + dingdingContentBuilder.Append("快车业务线-创意维度\n"); + isAddBusinessTypeTitle = true; + } + + dingdingContentBuilder.Append($"{dingdingWarningContent}\n"); + } + } + #endregion + + #region SKU精速推 + isAddBusinessTypeTitle = false; + + var skuGOIList = jDReportFormStatisticsBusiness.CalculationSkuLevelGOI(new SkuGOIRequest() + { + BusinessType = 134217728, + LevelIdList = skuIds, + OnlyCustomDate = true, + StartDate = yesterday, + EndDate = startQueryDay + }); + + foreach (var skuGOI in skuGOIList) + { + var sku = yesterdayJDpopularizeadskuList.FirstOrDefault(s => s.Sku == skuGOI.LevelId); + if (sku == null) + continue; + + var logContentBuilder = new StringBuilder(); + logContentBuilder.AppendLine($"SKU维度 {sku.CampaignName}({sku.CampaignId})-{sku.Sku}"); + + Enums.SiNanCycleType? siNanCycleType = Enums.SiNanCycleType.暂无周期; + bool isWarning = false; + string dingdingWarningContent = string.Empty; + + if (skuGOI.TotalCost < growupCost) + { + siNanCycleType = Enums.SiNanCycleType.成长加速期; + if (skuGOI.TotalCost < growupLevel1Cost) + { + //不建议调整 + isWarning = false; + } + else if (skuGOI.TotalCost >= growupLevel4Cost) + { + if (skuGOI.CustomDaysGOI.GOI < growupLevel4MinGOI) + { + isWarning = true; + dingdingWarningContent = $"{sku.CampaignName}-{sku.Sku} 处于{siNanCycleType},近7天GOI低于{growupLevel4MinGOI},请及时优化!"; + } + else if (skuGOI.CustomDaysGOI.GOI > growupLevel4MaxGOI) + { + isWarning = true; + dingdingWarningContent = $"{sku.CampaignName}-{sku.Sku} 处于{siNanCycleType},近7天GOI低于{growupLevel4MaxGOI},舍不得孩子套不住狼,请及时优化!"; + } + } + else if (skuGOI.TotalCost >= growupLevel3Cost) + { + if (skuGOI.CustomDaysGOI.GOI < growupLevel3MinGOI) + { + isWarning = true; + dingdingWarningContent = $"{sku.CampaignName}-{sku.Sku} 处于{siNanCycleType},近7天GOI低于{growupLevel3MinGOI},请及时优化!"; + } + else if (skuGOI.CustomDaysGOI.GOI < growupLevel3MaxGOI) + { + isWarning = true; + dingdingWarningContent = $"{sku.CampaignName}-{sku.Sku} 处于{siNanCycleType},近7天GOI低于{growupLevel3MaxGOI},舍不得孩子套不住狼,请及时优化!"; + } + } + else if (skuGOI.TotalCost >= growupLevel2Cost) + { + if (skuGOI.CustomDaysGOI.GOI < growupLevel2MinGOI) + { + isWarning = true; + dingdingWarningContent = $"{sku.CampaignName}-{sku.Sku} 处于{siNanCycleType},近7天GOI低于{growupLevel2MinGOI},请及时优化!"; + } + else if (skuGOI.CustomDaysGOI.GOI < growupLevel2MaxGOI) + { + isWarning = true; + dingdingWarningContent = $"{sku.CampaignName}-{sku.Sku} 处于{siNanCycleType},近7天GOI低于{growupLevel2MaxGOI},舍不得孩子套不住狼,请及时优化!"; + } + } + } + else if (skuGOI.TotalCost > matureCost && skuGOI.CustomDaysGOI.Cost > mature7dCost) + { + siNanCycleType = Enums.SiNanCycleType.成熟利润期; + if (skuGOI.CustomDaysGOI.GOI < matureLevel1MinGOI) + { + isWarning = true; + dingdingWarningContent = $"{sku.CampaignName}-{sku.Sku} 处于{siNanCycleType},近7天GOI低于{matureLevel1MinGOI},请及时优化!"; + } + else if (skuGOI.CustomDaysGOI.GOI > matureLevel1MaxGOI) + { + isWarning = true; + dingdingWarningContent = $"{sku.CampaignName}-{sku.Sku} 处于{siNanCycleType},近7天GOI低于{matureLevel1MaxGOI},舍不得孩子套不住狼,请及时优化!"; + } + } + else if (skuGOI.TotalCost > stableCost && skuGOI.CustomDaysGOI.Cost < stable7dCost) + { + siNanCycleType = Enums.SiNanCycleType.稳定日销期; + if (skuGOI.CustomDaysGOI.GOI < stableLevel1MinGOI) + { + isWarning = true; + dingdingWarningContent = $"{sku.CampaignName}-{sku.Sku} 处于{siNanCycleType},近7天GOI低于{stableLevel1MinGOI},请及时优化!"; + } + else if (skuGOI.CustomDaysGOI.GOI > stableLevel1MaxGOI) + { + isWarning = true; + dingdingWarningContent = $"{sku.CampaignName}-{sku.Sku} 处于{siNanCycleType},近7天GOI低于{stableLevel1MaxGOI},舍不得孩子套不住狼,请及时优化!"; + } + } + + logContentBuilder.AppendLine($"{siNanCycleType}"); + logContentBuilder.AppendLine($"累计推广花费{skuGOI.TotalCost}"); + logContentBuilder.AppendLine($"近7天花费{skuGOI.CustomDaysGOI.Cost}"); + logContentBuilder.AppendLine($"近7天GOI{skuGOI.CustomDaysGOI.GOI}"); + logContentBuilder.AppendLine($"是否出发预警{isWarning}"); + + if (isWarning) + { + isSendDingTalk = true; + if (!isAddBusinessTypeTitle) + { + dingdingContentBuilder.Append("京速推业务线-SKU维度\n"); + isAddBusinessTypeTitle = true; + } + + dingdingContentBuilder.Append($"{dingdingWarningContent}\n"); + } + } + #endregion + + if (isSendDingTalk) + dingDingBusiness.SendDingDingBotMessage(shop.SiNanDingDingKey, shop.SiNanDingDingWebHook, dingdingContentBuilder.ToString()); + } + catch (Exception ex) + { + nLogManager.GetLogger(loggerName).Error(ex, "GOI预警失败"); + } + } } } diff --git a/BBWY.Server.Business/Statistics/JDReportFormStatisticsBusiness.cs b/BBWY.Server.Business/Statistics/JDReportFormStatisticsBusiness.cs index 22c53e60..2f98c135 100644 --- a/BBWY.Server.Business/Statistics/JDReportFormStatisticsBusiness.cs +++ b/BBWY.Server.Business/Statistics/JDReportFormStatisticsBusiness.cs @@ -131,19 +131,29 @@ namespace BBWY.Server.Business.Statistics public IList CalculationAdGroupLevelGOI(GOIRequest gOIRequest) { - var _7dEndDate = DateTime.Now.Date.AddDays(-1); - var _7dStartDate = _7dEndDate.AddDays(-6); - var _7dEndTime = _7dEndDate.AddDays(1).AddSeconds(-1); + var customEndTime = gOIRequest.EndDate.AddDays(1).AddSeconds(-1); - var _30dEndDate = DateTime.Now.Date.AddDays(-1); - var _30dStartDate = _30dEndDate.AddDays(-29); - var _30dEndTime = _30dEndDate.AddDays(1).AddSeconds(-1); + DateTime? _7dEndDate = null; + DateTime? _7dStartDate = null; + DateTime? _7dEndTime = null; + DateTime? _30dEndDate = null; + DateTime? _30dStartDate = null; + DateTime? _30dEndTime = null; - var customEndTime = gOIRequest.EndDate.AddDays(1).AddSeconds(-1); + if (!gOIRequest.OnlyCustomDate) + { + _7dEndDate = DateTime.Now.Date.AddDays(-1); + _7dStartDate = _7dEndDate.Value.AddDays(-6); + _7dEndTime = _7dEndDate.Value.AddDays(1).AddSeconds(-1); + _30dEndDate = DateTime.Now.Date.AddDays(-1); + _30dStartDate = _30dEndDate.Value.AddDays(-29); + _30dEndTime = _30dEndDate.Value.AddDays(1).AddSeconds(-1); + } - var _7dAdGroupCosts = fsql.Select().Where(x => gOIRequest.LevelIdList.Contains(x.AdGroupId.Value) && - x.Date >= _7dStartDate && - x.Date <= _7dEndDate) + + var _7dAdGroupCosts = gOIRequest.OnlyCustomDate ? null : fsql.Select().Where(x => gOIRequest.LevelIdList.Contains(x.AdGroupId.Value) && + x.Date >= _7dStartDate && + x.Date <= _7dEndDate) .GroupBy(x => x.AdGroupId) .ToList(g => new { @@ -151,7 +161,7 @@ namespace BBWY.Server.Business.Statistics AdGroupId = g.Key }); - var _7dAdGroupProfits = fsql.Select().InnerJoin((jr, oc, o) => jr.OrderId == oc.OrderId) + var _7dAdGroupProfits = gOIRequest.OnlyCustomDate ? null : fsql.Select().InnerJoin((jr, oc, o) => jr.OrderId == oc.OrderId) .InnerJoin((jr, oc, o) => jr.OrderId == o.Id) .Where((jr, oc, o) => gOIRequest.LevelIdList.Contains(jr.AdGroupId.Value) && jr.CookieTime >= _7dStartDate && @@ -164,7 +174,7 @@ namespace BBWY.Server.Business.Statistics Profit = g.Sum(g.Value.Item2.Profit) }); - var _30dAdGroupCosts = fsql.Select().Where(x => gOIRequest.LevelIdList.Contains(x.AdGroupId.Value) && + var _30dAdGroupCosts = gOIRequest.OnlyCustomDate ? null : fsql.Select().Where(x => gOIRequest.LevelIdList.Contains(x.AdGroupId.Value) && x.Date >= _30dStartDate && x.Date <= _30dEndDate) .GroupBy(x => x.AdGroupId) @@ -174,7 +184,7 @@ namespace BBWY.Server.Business.Statistics AdGroupId = g.Key }); - var _30dAdGroupProfits = fsql.Select().InnerJoin((jr, oc, o) => jr.OrderId == oc.OrderId) + var _30dAdGroupProfits = gOIRequest.OnlyCustomDate ? null : fsql.Select().InnerJoin((jr, oc, o) => jr.OrderId == oc.OrderId) .InnerJoin((jr, oc, o) => jr.OrderId == o.Id) .Where((jr, oc, o) => gOIRequest.LevelIdList.Contains(jr.AdGroupId.Value) && jr.CookieTime >= _30dStartDate && @@ -226,11 +236,11 @@ namespace BBWY.Server.Business.Statistics LevelId = levelId, BusinessType = gOIRequest.BusinessType }; - goiResponse._7GOI.Cost = _7dAdGroupCosts.FirstOrDefault(x => x.AdGroupId == levelId)?.Cost ?? 0M; - goiResponse._7GOI.Profit = _7dAdGroupProfits.FirstOrDefault(x => x.AdGroupId == levelId)?.Profit ?? 0M; + goiResponse._7GOI.Cost = _7dAdGroupCosts == null ? 0 : (_7dAdGroupCosts.FirstOrDefault(x => x.AdGroupId == levelId)?.Cost ?? 0M); + goiResponse._7GOI.Profit = _7dAdGroupProfits == null ? 0 : (_7dAdGroupProfits.FirstOrDefault(x => x.AdGroupId == levelId)?.Profit ?? 0M); - goiResponse._30GOI.Cost = _30dAdGroupCosts.FirstOrDefault(x => x.AdGroupId == levelId)?.Cost ?? 0M; - goiResponse._30GOI.Profit = _30dAdGroupProfits.FirstOrDefault(x => x.AdGroupId == levelId)?.Profit ?? 0M; + goiResponse._30GOI.Cost = _30dAdGroupCosts == null ? 0 : (_30dAdGroupCosts.FirstOrDefault(x => x.AdGroupId == levelId)?.Cost ?? 0M); + goiResponse._30GOI.Profit = _30dAdGroupProfits == null ? 0 : (_30dAdGroupProfits.FirstOrDefault(x => x.AdGroupId == levelId)?.Profit ?? 0M); goiResponse.CustomDaysGOI.Cost = customDaysAdGroupCosts.FirstOrDefault(x => x.AdGroupId == levelId)?.Cost ?? 0M; goiResponse.CustomDaysGOI.Profit = customDaysAdGroupProfits.FirstOrDefault(x => x.AdGroupId == levelId)?.Profit ?? 0M; @@ -243,19 +253,28 @@ namespace BBWY.Server.Business.Statistics public IList CalculationAdLevelGOI(GOIRequest gOIRequest) { - var _7dEndDate = DateTime.Now.Date.AddDays(-1); - var _7dStartDate = _7dEndDate.AddDays(-6); - var _7dEndTime = _7dEndDate.AddDays(1).AddSeconds(-1); + var customEndTime = gOIRequest.EndDate.AddDays(1).AddSeconds(-1); - var _30dEndDate = DateTime.Now.Date.AddDays(-1); - var _30dStartDate = _30dEndDate.AddDays(-29); - var _30dEndTime = _30dEndDate.AddDays(1).AddSeconds(-1); + DateTime? _7dEndDate = null; + DateTime? _7dStartDate = null; + DateTime? _7dEndTime = null; + DateTime? _30dEndDate = null; + DateTime? _30dStartDate = null; + DateTime? _30dEndTime = null; - var customEndTime = gOIRequest.EndDate.AddDays(1).AddSeconds(-1); + if (!gOIRequest.OnlyCustomDate) + { + _7dEndDate = DateTime.Now.Date.AddDays(-1); + _7dStartDate = _7dEndDate.Value.AddDays(-6); + _7dEndTime = _7dEndDate.Value.AddDays(1).AddSeconds(-1); + _30dEndDate = DateTime.Now.Date.AddDays(-1); + _30dStartDate = _30dEndDate.Value.AddDays(-29); + _30dEndTime = _30dEndDate.Value.AddDays(1).AddSeconds(-1); + } - var _7dAdCosts = fsql.Select().Where(x => gOIRequest.LevelIdList.Contains(x.AdId.Value) && - x.Date >= _7dStartDate && - x.Date <= _7dEndDate) + var _7dAdCosts = gOIRequest.OnlyCustomDate ? null : fsql.Select().Where(x => gOIRequest.LevelIdList.Contains(x.AdId.Value) && + x.Date >= _7dStartDate && + x.Date <= _7dEndDate) .GroupBy(x => x.AdId) .ToList(g => new { @@ -263,7 +282,7 @@ namespace BBWY.Server.Business.Statistics AdId = g.Key }); - var _7dAdProfits = fsql.Select().InnerJoin((jr, oc, o) => jr.OrderId == oc.OrderId) + var _7dAdProfits = gOIRequest.OnlyCustomDate ? null : fsql.Select().InnerJoin((jr, oc, o) => jr.OrderId == oc.OrderId) .InnerJoin((jr, oc, o) => jr.OrderId == o.Id) .Where((jr, oc, o) => gOIRequest.LevelIdList.Contains(jr.AdId.Value) && jr.CookieTime >= _7dStartDate && @@ -276,7 +295,7 @@ namespace BBWY.Server.Business.Statistics Profit = g.Sum(g.Value.Item2.Profit) }); - var _30dAdCosts = fsql.Select().Where(x => gOIRequest.LevelIdList.Contains(x.AdId.Value) && + var _30dAdCosts = gOIRequest.OnlyCustomDate ? null : fsql.Select().Where(x => gOIRequest.LevelIdList.Contains(x.AdId.Value) && x.Date >= _30dStartDate && x.Date <= _30dEndDate) .GroupBy(x => x.AdId) @@ -286,7 +305,7 @@ namespace BBWY.Server.Business.Statistics AdId = g.Key }); - var _30dAdProfits = fsql.Select().InnerJoin((jr, oc, o) => jr.OrderId == oc.OrderId) + var _30dAdProfits = gOIRequest.OnlyCustomDate ? null : fsql.Select().InnerJoin((jr, oc, o) => jr.OrderId == oc.OrderId) .InnerJoin((jr, oc, o) => jr.OrderId == o.Id) .Where((jr, oc, o) => gOIRequest.LevelIdList.Contains(jr.AdId.Value) && jr.CookieTime >= _30dStartDate && @@ -338,11 +357,11 @@ namespace BBWY.Server.Business.Statistics LevelId = levelId, BusinessType = gOIRequest.BusinessType }; - goiResponse._7GOI.Cost = _7dAdCosts.FirstOrDefault(x => x.AdId == levelId)?.Cost ?? 0M; - goiResponse._7GOI.Profit = _7dAdProfits.FirstOrDefault(x => x.AdId == levelId)?.Profit ?? 0M; + goiResponse._7GOI.Cost = _7dAdCosts == null ? 0 : (_7dAdCosts.FirstOrDefault(x => x.AdId == levelId)?.Cost ?? 0M); + goiResponse._7GOI.Profit = _7dAdProfits == null ? 0 : (_7dAdProfits.FirstOrDefault(x => x.AdId == levelId)?.Profit ?? 0M); - goiResponse._30GOI.Cost = _30dAdCosts.FirstOrDefault(x => x.AdId == levelId)?.Cost ?? 0M; - goiResponse._30GOI.Profit = _30dAdProfits.FirstOrDefault(x => x.AdId == levelId)?.Profit ?? 0M; + goiResponse._30GOI.Cost = _30dAdCosts == null ? 0 : (_30dAdCosts.FirstOrDefault(x => x.AdId == levelId)?.Cost ?? 0M); + goiResponse._30GOI.Profit = _30dAdProfits == null ? 0 : (_30dAdProfits.FirstOrDefault(x => x.AdId == levelId)?.Profit ?? 0M); goiResponse.CustomDaysGOI.Cost = customDaysAdCosts.FirstOrDefault(x => x.AdId == levelId)?.Cost ?? 0M; goiResponse.CustomDaysGOI.Profit = customDaysAdProfits.FirstOrDefault(x => x.AdId == levelId)?.Profit ?? 0M; @@ -355,20 +374,29 @@ namespace BBWY.Server.Business.Statistics public IList CalculationSkuLevelGOI(SkuGOIRequest gOIRequest) { - var _7dEndDate = DateTime.Now.Date.AddDays(-1); - var _7dStartDate = _7dEndDate.AddDays(-6); - var _7dEndTime = _7dEndDate.AddDays(1).AddSeconds(-1); + var customEndTime = gOIRequest.EndDate.AddDays(1).AddSeconds(-1); - var _30dEndDate = DateTime.Now.Date.AddDays(-1); - var _30dStartDate = _30dEndDate.AddDays(-29); - var _30dEndTime = _30dEndDate.AddDays(1).AddSeconds(-1); + DateTime? _7dEndDate = null; + DateTime? _7dStartDate = null; + DateTime? _7dEndTime = null; + DateTime? _30dEndDate = null; + DateTime? _30dStartDate = null; + DateTime? _30dEndTime = null; - var customEndTime = gOIRequest.EndDate.AddDays(1).AddSeconds(-1); + if (!gOIRequest.OnlyCustomDate) + { + _7dEndDate = DateTime.Now.Date.AddDays(-1); + _7dStartDate = _7dEndDate.Value.AddDays(-6); + _7dEndTime = _7dEndDate.Value.AddDays(1).AddSeconds(-1); + _30dEndDate = DateTime.Now.Date.AddDays(-1); + _30dStartDate = _30dEndDate.Value.AddDays(-29); + _30dEndTime = _30dEndDate.Value.AddDays(1).AddSeconds(-1); + } - var _7dSkuCosts = fsql.Select().Where(x => gOIRequest.LevelIdList.Contains(x.Sku) && - x.BusinessType == 134217728 && - x.Date >= _7dStartDate && - x.Date <= _7dEndDate) + var _7dSkuCosts = gOIRequest.OnlyCustomDate ? null : fsql.Select().Where(x => gOIRequest.LevelIdList.Contains(x.Sku) && + x.BusinessType == 134217728 && + x.Date >= _7dStartDate && + x.Date <= _7dEndDate) .GroupBy(x => x.Sku) .ToList(g => new { @@ -376,7 +404,7 @@ namespace BBWY.Server.Business.Statistics Sku = g.Key }); - var _7dSkuProfits = fsql.Select().InnerJoin((jr, oc, o) => jr.OrderId == oc.OrderId) + var _7dSkuProfits = gOIRequest.OnlyCustomDate ? null : fsql.Select().InnerJoin((jr, oc, o) => jr.OrderId == oc.OrderId) .InnerJoin((jr, oc, o) => jr.OrderId == o.Id) .Where((jr, oc, o) => gOIRequest.LevelIdList.Contains(jr.PopularizeSku) && jr.BusinessType == 134217728 && @@ -390,7 +418,7 @@ namespace BBWY.Server.Business.Statistics Profit = g.Sum(g.Value.Item2.Profit) }); - var _30dSkuCosts = fsql.Select().Where(x => gOIRequest.LevelIdList.Contains(x.Sku) && + var _30dSkuCosts = gOIRequest.OnlyCustomDate ? null : fsql.Select().Where(x => gOIRequest.LevelIdList.Contains(x.Sku) && x.BusinessType == 134217728 && x.Date >= _30dStartDate && x.Date <= _30dEndDate) @@ -401,7 +429,7 @@ namespace BBWY.Server.Business.Statistics Sku = g.Key }); - var _30dSkuProfits = fsql.Select().InnerJoin((jr, oc, o) => jr.OrderId == oc.OrderId) + var _30dSkuProfits = gOIRequest.OnlyCustomDate ? null : fsql.Select().InnerJoin((jr, oc, o) => jr.OrderId == oc.OrderId) .InnerJoin((jr, oc, o) => jr.OrderId == o.Id) .Where((jr, oc, o) => gOIRequest.LevelIdList.Contains(jr.PopularizeSku) && jr.BusinessType == 134217728 && @@ -458,11 +486,11 @@ namespace BBWY.Server.Business.Statistics LevelId = levelId, BusinessType = gOIRequest.BusinessType }; - goiResponse._7GOI.Cost = _7dSkuCosts.FirstOrDefault(x => x.Sku == levelId)?.Cost ?? 0M; - goiResponse._7GOI.Profit = _7dSkuProfits.FirstOrDefault(x => x.Sku == levelId)?.Profit ?? 0M; + goiResponse._7GOI.Cost = _7dSkuCosts == null ? 0 : (_7dSkuCosts.FirstOrDefault(x => x.Sku == levelId)?.Cost ?? 0M); + goiResponse._7GOI.Profit = _7dSkuProfits == null ? 0 : (_7dSkuProfits.FirstOrDefault(x => x.Sku == levelId)?.Profit ?? 0M); - goiResponse._30GOI.Cost = _30dSkuCosts.FirstOrDefault(x => x.Sku == levelId)?.Cost ?? 0M; - goiResponse._30GOI.Profit = _30dSkuProfits.FirstOrDefault(x => x.Sku == levelId)?.Profit ?? 0M; + goiResponse._30GOI.Cost = _30dSkuCosts == null ? 0 : (_30dSkuCosts.FirstOrDefault(x => x.Sku == levelId)?.Cost ?? 0M); + goiResponse._30GOI.Profit = _30dSkuProfits == null ? 0 : (_30dSkuProfits.FirstOrDefault(x => x.Sku == levelId)?.Profit ?? 0M); goiResponse.CustomDaysGOI.Cost = customDaysSkuCosts.FirstOrDefault(x => x.Sku == levelId)?.Cost ?? 0M; goiResponse.CustomDaysGOI.Profit = customDaysSkuProfits.FirstOrDefault(x => x.Sku == levelId)?.Profit ?? 0M; diff --git a/BBWY.Server.Business/TaskSchedulerManager.cs b/BBWY.Server.Business/TaskSchedulerManager.cs index c9e68705..1b8cd3d0 100644 --- a/BBWY.Server.Business/TaskSchedulerManager.cs +++ b/BBWY.Server.Business/TaskSchedulerManager.cs @@ -20,6 +20,8 @@ namespace BBWY.Server.Business public LimitedConcurrencyLevelTaskScheduler StockNumWarningTaskScheduler { get; private set; } + public LimitedConcurrencyLevelTaskScheduler GOIWarningTaskScheduler { get; private set; } + public TaskSchedulerManager() { SyncOrderTaskScheduler = new LimitedConcurrencyLevelTaskScheduler(10); @@ -32,6 +34,7 @@ namespace BBWY.Server.Business StoreHouseTaskScheduler = new LimitedConcurrencyLevelTaskScheduler(2); StockNumWarningTaskScheduler = new LimitedConcurrencyLevelTaskScheduler(10); + GOIWarningTaskScheduler = new LimitedConcurrencyLevelTaskScheduler(10); } } } diff --git a/BBWY.Server.Business/Vender/VenderBusiness.cs b/BBWY.Server.Business/Vender/VenderBusiness.cs index 5b9a88d5..f2977973 100644 --- a/BBWY.Server.Business/Vender/VenderBusiness.cs +++ b/BBWY.Server.Business/Vender/VenderBusiness.cs @@ -246,12 +246,13 @@ namespace BBWY.Server.Business return departmentList; } - public IList GetShopList(long? shopId = null, Enums.Platform? platform = null, bool filterTurnoverDays = false) + public IList GetShopList(long? shopId = null, Enums.Platform? platform = null, bool filterTurnoverDays = false, bool filterSiNan = false) { return freeSqlMultiDBManager.MDSfsql.Select().Where(s => !string.IsNullOrEmpty(s.ShopId)) .WhereIf(shopId != null, s => s.ShopId == shopId.ToString()) .WhereIf(platform != null, s => s.PlatformId == (int)platform) .WhereIf(filterTurnoverDays, s => s.SkuSafeTurnoverDays != 0) + .WhereIf(filterSiNan, s => !string.IsNullOrEmpty(s.SiNanDingDingWebHook)) .ToList(); } diff --git a/BBWY.Server.Model/Dto/Request/Statistics/GOIRequest.cs b/BBWY.Server.Model/Dto/Request/Statistics/GOIRequest.cs index 885c6008..ad9279ed 100644 --- a/BBWY.Server.Model/Dto/Request/Statistics/GOIRequest.cs +++ b/BBWY.Server.Model/Dto/Request/Statistics/GOIRequest.cs @@ -23,6 +23,8 @@ namespace BBWY.Server.Model.Dto public DateTime StartDate { get; set; } public DateTime EndDate { get; set; } + + public bool OnlyCustomDate { get; set; } } public class SkuGOIRequest: GOIRequest diff --git a/BBWY.Server.Model/Enums.cs b/BBWY.Server.Model/Enums.cs index de33c121..6465c019 100644 --- a/BBWY.Server.Model/Enums.cs +++ b/BBWY.Server.Model/Enums.cs @@ -223,5 +223,17 @@ 稳定期 = 2, 衰退期 = 3 } + + /// + /// 司南周期 暂无周期 = -1,成长加速期 = 0,成熟利润期 = 1,稳定日销期 = 2,策马奔腾期 = 3 + /// + public enum SiNanCycleType + { + 暂无周期 = -1, + 成长加速期 = 0, + 成熟利润期 = 1, + 稳定日销期 = 2, + 策马奔腾期 = 3 + } } }