Compare commits
2 Commits
Author | SHA1 | Date |
---|---|---|
|
94a2cb092b | 2 years ago |
|
5047f1d47b | 2 years ago |
14 changed files with 937 additions and 0 deletions
@ -0,0 +1,87 @@ |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using SBF.Business; |
|||
using SBF.Model.Dto; |
|||
|
|||
namespace SBF.API.Controllers |
|||
{ |
|||
/// <summary>
|
|||
/// 执行托管策略
|
|||
/// </summary>
|
|||
public class ExecuteTrusteeshipPolicyController : BaseApiController |
|||
{ |
|||
|
|||
private ExecuteTrusteeshipPolicyBusiness executeTrusteeshipPolicyBusiness; |
|||
|
|||
public ExecuteTrusteeshipPolicyController(IHttpContextAccessor httpContextAccessor, ExecuteTrusteeshipPolicyBusiness executeTrusteeshipPolicyBusiness) : base(httpContextAccessor) |
|||
{ |
|||
this.executeTrusteeshipPolicyBusiness = executeTrusteeshipPolicyBusiness; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 批量上传店铺预算数据(回调地址)
|
|||
/// </summary>
|
|||
/// <param name="requestList"></param>
|
|||
[HttpPost] |
|||
[AllowAnonymous] |
|||
public async Task BatchUpdateBudget(BatchUpdateBudgetRequest[] requestList) |
|||
{ |
|||
await executeTrusteeshipPolicyBusiness.BatchUpdateBudget(requestList); |
|||
} |
|||
|
|||
|
|||
/// <summary>
|
|||
/// 批量上传店铺单元出价数据(回调地址)
|
|||
/// </summary>
|
|||
/// <param name="requestList"></param>
|
|||
[HttpPost] |
|||
[AllowAnonymous] |
|||
public async Task BatchUpdateBidPrice(BatchUpdateBidPriceRequest[] requestList) |
|||
{ |
|||
await executeTrusteeshipPolicyBusiness.BatchUpdateBidPrice(requestList); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 更新策略数据(当日预算. 出价 ,当前时间花费情况) 9:00
|
|||
/// </summary>
|
|||
[HttpGet] |
|||
[AllowAnonymous] |
|||
public async Task UpdateTrusteeshipPolicyData() |
|||
{ |
|||
await executeTrusteeshipPolicyBusiness.UpdateTrusteeshipPolicyData(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 判断 预算耗尽 更新出价 花费 预算
|
|||
/// </summary>
|
|||
/// <returns></returns>
|
|||
[HttpGet] |
|||
[AllowAnonymous] |
|||
public async Task JudgeBudgetCostOutUpdateTrusteeshipPolicyData() |
|||
{ |
|||
await executeTrusteeshipPolicyBusiness.JudgeBudgetCostOutUpdateTrusteeshipPolicyData(); |
|||
} |
|||
|
|||
|
|||
/// <summary>
|
|||
/// 运行成长期调高出价策略
|
|||
/// </summary>
|
|||
/// <returns></returns>
|
|||
[HttpGet] |
|||
[AllowAnonymous] |
|||
public async Task RunGrowthPeriodIncreaseBidPriceTrusteeshipPolicy() |
|||
{ |
|||
await executeTrusteeshipPolicyBusiness.RunGrowthPeriodIncreaseBidPriceTrusteeshipPolicy(); |
|||
} |
|||
/// <summary>
|
|||
/// 运行成长期降低出价策略
|
|||
/// </summary>
|
|||
/// <returns></returns>
|
|||
[HttpGet] |
|||
[AllowAnonymous] |
|||
public async Task RunGrowthPeriodLowerBidPriceTrusteeshipPolicy() |
|||
{ |
|||
await executeTrusteeshipPolicyBusiness.RunGrowthPeriodLowerBidPriceTrusteeshipPolicy(); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,60 @@ |
|||
using CSRedis; |
|||
using Microsoft.Extensions.Caching.Distributed; |
|||
using Microsoft.Extensions.Caching.Redis; |
|||
using System.Security.AccessControl; |
|||
|
|||
|
|||
namespace SBF.API.Extentions |
|||
{ |
|||
public static class HostExtentions |
|||
{ |
|||
/// <summary>
|
|||
/// 使用缓存
|
|||
/// </summary>
|
|||
/// <param name="hostBuilder">建造者</param>
|
|||
/// <returns></returns>
|
|||
public static IHostBuilder UseCache(this IHostBuilder hostBuilder) |
|||
{ |
|||
|
|||
|
|||
hostBuilder.ConfigureServices((buidlerContext, services) => |
|||
{ |
|||
var cacheOption = buidlerContext.Configuration.GetSection("Cache").Get<CacheOptions>(); |
|||
switch (cacheOption.CacheType) |
|||
{ |
|||
case CacheType.Memory: services.AddDistributedMemoryCache(); break; |
|||
case CacheType.Redis: |
|||
{ |
|||
var csredis = new CSRedisClient(cacheOption.RedisEndpoint); |
|||
RedisHelper.Initialization(csredis); |
|||
services.AddSingleton(csredis); |
|||
services.AddSingleton<IDistributedCache>(new CSRedisCache(RedisHelper.Instance)); |
|||
}; break; |
|||
default: throw new Exception("缓存类型无效"); |
|||
} |
|||
}); |
|||
|
|||
return hostBuilder; |
|||
} |
|||
|
|||
} |
|||
internal class CacheOptions |
|||
{ |
|||
public CacheType CacheType { get; set; } |
|||
public string RedisEndpoint { get; set; } |
|||
} /// <summary>
|
|||
/// 缓存类型
|
|||
/// </summary>
|
|||
public enum CacheType |
|||
{ |
|||
/// <summary>
|
|||
/// 使用内存缓存(不支持分布式)
|
|||
/// </summary>
|
|||
Memory, |
|||
|
|||
/// <summary>
|
|||
/// 使用Redis缓存(支持分布式)
|
|||
/// </summary>
|
|||
Redis |
|||
} |
|||
} |
@ -0,0 +1,586 @@ |
|||
using Google.Protobuf.WellKnownTypes; |
|||
using Microsoft.Extensions.Caching.Distributed; |
|||
using Newtonsoft.Json; |
|||
using NLog; |
|||
using SBF.Common.Log; |
|||
using SBF.Common.Models; |
|||
using SBF.Model.Db; |
|||
using SBF.Model.Db.Trusteeship; |
|||
using SBF.Model.Dto; |
|||
using SiNan.Business; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Net.Http; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
using Yitter.IdGenerator; |
|||
|
|||
namespace SBF.Business |
|||
{ |
|||
/// <summary>
|
|||
/// 执行托管策略
|
|||
/// </summary>
|
|||
public class ExecuteTrusteeshipPolicyBusiness : BaseBusiness, IDenpendency |
|||
{ |
|||
|
|||
ILogger logger; |
|||
public ExecuteTrusteeshipPolicyBusiness(IFreeSql fsql, NLogManager nLogManager, IIdGenerator idGenerator, IDistributedCache cache) : base(fsql, nLogManager, idGenerator) |
|||
{ |
|||
logger = nLogManager.GetLogger("执行托管策略"); |
|||
_cache = cache; |
|||
|
|||
} |
|||
|
|||
|
|||
readonly IDistributedCache _cache; |
|||
|
|||
string host = "http://api.sbf.qiyue666.com/"; |
|||
|
|||
/// <summary>
|
|||
/// 回调出价和花费
|
|||
/// </summary>
|
|||
/// <param name="requestList"></param>
|
|||
/// <returns></returns>
|
|||
/// <exception cref="NotImplementedException"></exception>
|
|||
public async Task BatchUpdateBidPrice(BatchUpdateBidPriceRequest[] requestList) |
|||
{ |
|||
|
|||
|
|||
var AdgroupIdList = requestList.Select(r => long.Parse(r.AdgroupId)).ToList(); |
|||
var trusteeshipTaskList = fsql.Select<Sbf_TrusteeshipTask>().Where(s => s.AdGroupId != null && AdgroupIdList.Contains(s.AdGroupId.Value)).ToList(); |
|||
foreach (var trusteeshipTask in trusteeshipTaskList) |
|||
{ |
|||
var newData = requestList.FirstOrDefault(t => t.AdgroupId == trusteeshipTask.AdGroupId?.ToString()); |
|||
|
|||
if (newData != null) |
|||
{ |
|||
trusteeshipTask.BidPrice = newData.SearchFee;//当前出价
|
|||
trusteeshipTask.NowCost = newData.TotalCost;//当前总花费
|
|||
continue; |
|||
} |
|||
|
|||
} |
|||
if (trusteeshipTaskList.Any()) |
|||
await fsql.Update<Sbf_TrusteeshipTask>(trusteeshipTaskList).ExecuteUpdatedAsync(); |
|||
|
|||
|
|||
logger.Info($"回调出价和花费成功!回调消息:{JsonConvert.SerializeObject(requestList)}"); |
|||
|
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 回调预算
|
|||
/// </summary>
|
|||
/// <param name="requestList"></param>
|
|||
/// <returns></returns>
|
|||
/// <exception cref="NotImplementedException"></exception>
|
|||
public async Task BatchUpdateBudget(BatchUpdateBudgetRequest[] requestList) |
|||
{ |
|||
|
|||
var CampaignIdList = requestList.Select(r => long.Parse(r.CampaignId)).ToList(); |
|||
var trusteeshipTaskList = fsql.Select<Sbf_TrusteeshipTask>().Where(s => s.CampaignId != null && CampaignIdList.Contains(s.CampaignId.Value)).ToList(); |
|||
|
|||
|
|||
foreach (var trusteeshipTask in trusteeshipTaskList) |
|||
{ |
|||
var newData = requestList.FirstOrDefault(t => t.CampaignId == trusteeshipTask.CampaignId?.ToString()); |
|||
|
|||
if (newData != null) |
|||
{ |
|||
trusteeshipTask.Budget = newData.Budget; |
|||
continue; |
|||
} |
|||
|
|||
} |
|||
if (trusteeshipTaskList.Any()) |
|||
await fsql.Update<Sbf_TrusteeshipTask>(trusteeshipTaskList).ExecuteUpdatedAsync(); |
|||
|
|||
logger.Info($"回调预算成功!回调消息:{JsonConvert.SerializeObject(requestList)}"); |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
/// <summary>
|
|||
/// 提交
|
|||
/// </summary>
|
|||
/// <returns></returns>
|
|||
/// <exception cref="NotImplementedException"></exception>
|
|||
public async Task UpdateTrusteeshipPolicyData() |
|||
{ |
|||
//获取当前待执行列表的数据
|
|||
var searchTrusteeshipTaskList = FirstWeekUpdateTrusteeshipPolicyData(); |
|||
searchTrusteeshipTaskList.AddRange(OverFirstWeekUpdateTrusteeshipPolicyData()); |
|||
await UpdateTrusteeshipPolicyData(searchTrusteeshipTaskList); |
|||
|
|||
await ThreeWeekUpdateBudget();//第三周或三周以上 每天初始化预算
|
|||
} |
|||
|
|||
|
|||
private async Task UpdateTrusteeshipPolicyData(List<Sbf_TrusteeshipTask> searchTrusteeshipTaskList) |
|||
{ |
|||
var shopIds = searchTrusteeshipTaskList.Select(s => s.ShopId).Distinct().ToList(); |
|||
|
|||
|
|||
|
|||
|
|||
foreach (var shopId in shopIds) |
|||
{ |
|||
var CampaignIds = searchTrusteeshipTaskList.Where(s => s.ShopId == shopId).Select(s => s.CampaignId).Distinct().ToArray(); |
|||
|
|||
|
|||
/* |
|||
{ |
|||
"UserPin": "string", |
|||
"ShopId": "string", |
|||
"Start": "2023-12-02T06:08:15.492Z", |
|||
"End": "2023-12-02T06:08:15.492Z", |
|||
"ApiUrl": "string", |
|||
"CampaignIds": [ |
|||
"string" |
|||
] |
|||
} |
|||
*/ |
|||
string url = "http://txapi.sbf.qiyue666.com/SanBanFu/Api/SendGetBudgetByCampaignList"; |
|||
HttpClient client = new HttpClient(); |
|||
client.Timeout = TimeSpan.FromMinutes(1); |
|||
|
|||
var postData = JsonConvert.SerializeObject(new |
|||
{ |
|||
ShopId = shopId.ToString(), |
|||
Start = DateTime.Now.ToString(), |
|||
End = DateTime.Now.ToString(), |
|||
ApiUrl = host + "api/ExecuteTrusteeshipPolicy/BatchUpdateBudget", |
|||
CampaignIds = CampaignIds |
|||
}); |
|||
|
|||
HttpContent content = new StringContent(postData); |
|||
|
|||
var res = await client.PostAsync(url, content); |
|||
if (res.IsSuccessStatusCode) |
|||
{ |
|||
//发送成功
|
|||
logger.Info($"请求预算接口成功! 店铺id:{shopId},请求参数{postData}"); |
|||
|
|||
//todo: redis
|
|||
//await _cache.SetStringAsync("SBF:GetBudget:shopId", "0");//0未处理 三板斧批量获取预算
|
|||
|
|||
} |
|||
else |
|||
{ |
|||
logger.Error($"请求预算接口失败,返回消息:{res?.Content?.ReadAsStringAsync()?.Result}, 店铺id:{shopId},请求参数{postData}"); |
|||
} |
|||
Thread.Sleep(500); |
|||
/* |
|||
{ |
|||
"UserPin": "string", |
|||
"ShopId": "string", |
|||
"Start": "2023-12-02T06:59:26.115Z", |
|||
"End": "2023-12-02T06:59:26.115Z", |
|||
"ApiUrl": "string", |
|||
"AdgroupIds": [ |
|||
"string" |
|||
] |
|||
} |
|||
*/ |
|||
|
|||
var adgroupIds = searchTrusteeshipTaskList.Where(s => s.ShopId == shopId).Select(s => s.AdGroupId).Distinct().ToArray(); |
|||
url = "http://txapi.sbf.qiyue666.com/SanBanFu/Api/SendGetFeeByAdgroupList"; |
|||
postData = JsonConvert.SerializeObject(new |
|||
{ |
|||
ShopId = shopId.ToString(), |
|||
Start = DateTime.Now.ToString(), |
|||
End = DateTime.Now.ToString(), |
|||
ApiUrl = host + "api/ExecuteTrusteeshipPolicy/BatchUpdateBudget", |
|||
AdgroupIds = adgroupIds |
|||
}); |
|||
content = new StringContent(postData); |
|||
res = await client.PostAsync(url, content); |
|||
if (res.IsSuccessStatusCode) |
|||
{ |
|||
//发送成功
|
|||
logger.Info($"请求出价接口成功! 店铺id:{shopId},请求参数{postData}"); |
|||
|
|||
} |
|||
else |
|||
{ |
|||
logger.Error($"请求出价接口失败,返回消息:{res?.Content?.ReadAsStringAsync()?.Result}, 店铺id:{shopId},请求参数{postData}"); |
|||
} |
|||
Thread.Sleep(500); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 第一周 只需更新一次
|
|||
/// </summary>
|
|||
/// <returns></returns>
|
|||
private List<Sbf_TrusteeshipTask> FirstWeekUpdateTrusteeshipPolicyData() |
|||
{ |
|||
List<DateTime> excuteDate = new List<DateTime>(); |
|||
DateTime nowDate = DateTime.Now.Date; |
|||
|
|||
excuteDate.Add(nowDate.AddDays(4)); |
|||
excuteDate.Add(nowDate.AddDays(7)); |
|||
return fsql.Select<Sbf_TrusteeshipTask>().Where(s => s.IsEnd == false && s.PolicyType == Model.Enums.PolicyType.成长期策略包 && s.StartTrusteeshipDate != null && excuteDate.Contains(s.StartTrusteeshipDate.Value)).ToList();//
|
|||
} |
|||
/// <summary>
|
|||
/// 两周以上的(12:00 18:00 23:00要更新)
|
|||
/// </summary>
|
|||
/// <returns></returns>
|
|||
private List<Sbf_TrusteeshipTask> OverFirstWeekUpdateTrusteeshipPolicyData() |
|||
{ |
|||
List<DateTime> excuteDate = new List<DateTime>(); |
|||
DateTime nowDate = DateTime.Now.Date; |
|||
|
|||
excuteDate.Add(nowDate.AddDays(11)); |
|||
excuteDate.Add(nowDate.AddDays(14)); |
|||
return fsql.Select<Sbf_TrusteeshipTask>().Where(s => s.IsEnd == false && s.PolicyType == Model.Enums.PolicyType.成长期策略包 && s.StartTrusteeshipDate != null && (excuteDate.Contains(s.StartTrusteeshipDate.Value) || nowDate.AddDays(-15) >= s.StartTrusteeshipDate.Value)).ToList(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 更新
|
|||
/// </summary>
|
|||
private async Task ThreeWeekUpdateBudget() |
|||
{ |
|||
DateTime nowDate = DateTime.Now.Date; |
|||
//第三周 或者三周以上的数据
|
|||
var trusteeshipTaskList = fsql.Select<Sbf_TrusteeshipTask>().Where(s => s.IsEnd == false && s.PolicyType == Model.Enums.PolicyType.成长期策略包 && s.StartTrusteeshipDate != null && (nowDate.AddDays(-15) >= s.StartTrusteeshipDate.Value)).ToList(); |
|||
var primarySkuIdList = trusteeshipTaskList.Select(d => d.PrimarySkuId).Distinct().ToList(); |
|||
List<DateTime> excuteDate = new List<DateTime> |
|||
{ |
|||
nowDate.AddDays(-1), |
|||
nowDate.AddDays(-2), |
|||
nowDate.AddDays(-3) |
|||
}; |
|||
|
|||
var primarySkuDailyList = fsql.Select<AggregationJDPopularizeSkuDaily>().Where(a => primarySkuIdList.Contains(a.SkuId) && a.Date != null && excuteDate.Contains(a.Date.Value)).ToList(); |
|||
List<Sbf_AdjustLog> AdjustLogList = new List<Sbf_AdjustLog>(); |
|||
|
|||
var update = fsql.Update<Sbf_TrusteeshipTask>(); |
|||
foreach (var trusteeshipTask in trusteeshipTaskList) |
|||
{ |
|||
var primarySkuProfit = primarySkuDailyList.Where(p => p.SkuId == trusteeshipTask.PrimarySkuId).Select(p => p.ProductLevelProfit - p.Cost).Average();//3天日均盈利
|
|||
|
|||
if (trusteeshipTask.AnchorBudget == null) |
|||
{ |
|||
//todo: 提醒设置锚定预算
|
|||
continue; |
|||
} |
|||
decimal newBudget = primarySkuProfit.Value + trusteeshipTask.AnchorBudget.Value; |
|||
|
|||
|
|||
string adjustContent = string.Empty; |
|||
if (primarySkuProfit < 0) |
|||
{ |
|||
newBudget = trusteeshipTask.AnchorBudget.Value; |
|||
|
|||
} |
|||
adjustContent = $"主Sku:{trusteeshipTask.PrimarySkuId},近三天日均收益:{primarySkuProfit}"; |
|||
decimal oldBudget = trusteeshipTask.Budget.Value;//
|
|||
|
|||
|
|||
trusteeshipTask.Budget = newBudget;//更新预算
|
|||
|
|||
update.Where(u => u.Id == trusteeshipTask.Id).Set(u=>u.Budget, newBudget); |
|||
|
|||
//修改预算
|
|||
|
|||
//更新快车的 出价
|
|||
string url = "http://txapi.sbf.qiyue666.com/SanBanFu/Api/SendBudgetUpdate"; |
|||
HttpClient client = new HttpClient(); |
|||
client.Timeout = TimeSpan.FromMinutes(1); |
|||
|
|||
var postData = JsonConvert.SerializeObject(new |
|||
{ |
|||
ShopId = trusteeshipTask.ShopId?.ToString(), |
|||
CampaignId = trusteeshipTask.CampaignId?.ToString(), |
|||
DayBudget = newBudget |
|||
|
|||
}); |
|||
|
|||
HttpContent content = new StringContent(postData); |
|||
|
|||
var res = await client.PostAsync(url, content); |
|||
if (res.IsSuccessStatusCode) |
|||
{ |
|||
//发送成功
|
|||
logger.Info($"请求变更出价接口成功! 店铺id:{trusteeshipTask.ShopId},请求参数{postData}"); |
|||
|
|||
AdjustLogList.Add(new Sbf_AdjustLog |
|||
{ |
|||
AdjustType = Model.Enums.AdjustType.出价, |
|||
AdjustWay = Model.Enums.AdjustWay.调高, |
|||
CreateTime = DateTime.Now, |
|||
PolicyType = Model.Enums.PolicyType.成长期策略包, |
|||
TrusteeshipTaskId = trusteeshipTask.Id, |
|||
OperateContent = $"{adjustContent},原预算:{oldBudget},调整后预算:{newBudget}" |
|||
}); |
|||
|
|||
} |
|||
else |
|||
{ |
|||
logger.Error($"请求变更出价接口失败,返回消息:{res?.Content?.ReadAsStringAsync()?.Result}, 店铺id:{trusteeshipTask.ShopId},请求参数{postData}"); |
|||
} |
|||
Thread.Sleep(500); |
|||
} |
|||
|
|||
await update.ExecuteUpdatedAsync();//批量更新
|
|||
|
|||
|
|||
if (AdjustLogList.Any()) |
|||
await fsql.Insert<Sbf_AdjustLog>(AdjustLogList).ExecuteInsertedAsync(); |
|||
|
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
/// <summary>
|
|||
/// 更新第二周 4 7天 和三周以上的数据
|
|||
/// </summary>
|
|||
/// <returns></returns>
|
|||
public async Task JudgeBudgetCostOutUpdateTrusteeshipPolicyData() |
|||
{ |
|||
var searchTrusteeshipTaskList = OverFirstWeekUpdateTrusteeshipPolicyData(); |
|||
await UpdateTrusteeshipPolicyData(searchTrusteeshipTaskList); |
|||
} |
|||
|
|||
|
|||
/// <summary>
|
|||
/// 调高出价策略
|
|||
/// </summary>
|
|||
/// <returns></returns>
|
|||
/// <exception cref="NotImplementedException"></exception>
|
|||
public async Task RunGrowthPeriodIncreaseBidPriceTrusteeshipPolicy() |
|||
{ |
|||
/* |
|||
4 7 11 14 14天以上 |
|||
*/ |
|||
//获取当前待执行列表的数据
|
|||
var searchTrusteeshipTaskList = FirstWeekUpdateTrusteeshipPolicyData();// 4 7天
|
|||
searchTrusteeshipTaskList.AddRange(OverFirstWeekUpdateTrusteeshipPolicyData());//满足条件的数据
|
|||
|
|||
var adgroupIds = searchTrusteeshipTaskList.Select(s => s.AdGroupId).Distinct().ToArray(); |
|||
|
|||
|
|||
|
|||
|
|||
//获取满足条件的所有单元 前三天花费的数据
|
|||
|
|||
List<DateTime> excuteDate = new List<DateTime>(); |
|||
DateTime nowDate = DateTime.Now.Date; |
|||
|
|||
excuteDate.Add(nowDate.AddDays(-1)); |
|||
excuteDate.Add(nowDate.AddDays(-2)); |
|||
excuteDate.Add(nowDate.AddDays(-3)); |
|||
|
|||
|
|||
|
|||
|
|||
//获取前三天花费
|
|||
var adgroupCostList = fsql.Select<AggregationJDPopularizeAdGroupDaily>().Where(s => adgroupIds.Contains(s.AdGroupId) && s.Date != null && excuteDate.Contains(s.Date.Value)).ToList(); |
|||
|
|||
|
|||
List<Sbf_AdjustLog> AdjustLogList = new List<Sbf_AdjustLog>(); |
|||
var update = fsql.Update<Sbf_TrusteeshipTask>(); |
|||
foreach (var trusteeshipTask in searchTrusteeshipTaskList) |
|||
{ |
|||
var beforeThreeDayMaxCost = adgroupCostList.Where(a => a.AdGroupId == trusteeshipTask.AdGroupId).Select(s => s.Cost).Max();//前三天花费最高
|
|||
if (trusteeshipTask.BidPrice == null || trusteeshipTask.BidPrice == 0) |
|||
{ |
|||
logger.Error($"出价未获取,或者获取的出价为0,店铺id:{trusteeshipTask.ShopId},任务Id{trusteeshipTask.Id}"); |
|||
continue; |
|||
} |
|||
if (trusteeshipTask.Budget == null || trusteeshipTask.Budget == 0) |
|||
{ |
|||
logger.Error($"预算未获取,或者获取的预算为0,店铺id:{trusteeshipTask.ShopId},任务Id{trusteeshipTask.Id}"); |
|||
continue; |
|||
} |
|||
decimal newBidPrice = 0m; |
|||
string adjustContent = string.Empty; |
|||
if (beforeThreeDayMaxCost < trusteeshipTask.Budget.Value * 0.3m)//前三天花费最高的一天低于预算的30% 出价调高50%
|
|||
{ |
|||
newBidPrice = Math.Round(trusteeshipTask.BidPrice.Value * (1 + 0.5m), 2); |
|||
adjustContent = "出价调高50%"; |
|||
} |
|||
else if (beforeThreeDayMaxCost < trusteeshipTask.Budget.Value * 0.5m)//前三天花费最高的一天低于预算的50% 出价调高35%
|
|||
{ |
|||
newBidPrice = Math.Round(trusteeshipTask.BidPrice.Value * (1 + 0.35m), 2); |
|||
adjustContent = "出价调高35%"; |
|||
} |
|||
else if (beforeThreeDayMaxCost < trusteeshipTask.Budget.Value * 0.7m)//前三天花费最高的一天低于预算的70% 出价调高20%
|
|||
{ |
|||
newBidPrice = Math.Round(trusteeshipTask.BidPrice.Value * (1 + 0.2m), 2); |
|||
adjustContent = "出价调高20%"; |
|||
} |
|||
else |
|||
{ |
|||
logger.Info($"任务Id:{trusteeshipTask.Id},三天最高花费:{beforeThreeDayMaxCost},预算:{trusteeshipTask.BidPrice}"); |
|||
continue; |
|||
} |
|||
decimal oldBidPrice = trusteeshipTask.BidPrice.Value; |
|||
|
|||
trusteeshipTask.BidPrice = newBidPrice;//表里更新 新的出价
|
|||
update.Where(u => u.Id == trusteeshipTask.Id).Set(u => u.BidPrice, newBidPrice); |
|||
//更新快车的 出价
|
|||
string url = "http://txapi.sbf.qiyue666.com/SanBanFu/Api/SendFeeUpdate"; |
|||
HttpClient client = new HttpClient(); |
|||
client.Timeout = TimeSpan.FromMinutes(1); |
|||
|
|||
var postData = JsonConvert.SerializeObject(new |
|||
{ |
|||
ShopId = trusteeshipTask.ShopId?.ToString(), |
|||
AdgroupId = trusteeshipTask.AdGroupId?.ToString(), |
|||
SearchFee = newBidPrice |
|||
|
|||
}); |
|||
|
|||
HttpContent content = new StringContent(postData); |
|||
|
|||
var res = await client.PostAsync(url, content); |
|||
if (res.IsSuccessStatusCode) |
|||
{ |
|||
//发送成功
|
|||
logger.Info($"请求变更出价接口成功! 店铺id:{trusteeshipTask.ShopId},请求参数{postData}"); |
|||
|
|||
AdjustLogList.Add(new Sbf_AdjustLog |
|||
{ |
|||
AdjustType = Model.Enums.AdjustType.出价, |
|||
AdjustWay = Model.Enums.AdjustWay.调高, |
|||
CreateTime = DateTime.Now, |
|||
PolicyType = Model.Enums.PolicyType.成长期策略包, |
|||
TrusteeshipTaskId = trusteeshipTask.Id, |
|||
OperateContent = $"{adjustContent},原出价:{oldBidPrice},调整后出价:{newBidPrice}" |
|||
}); |
|||
|
|||
} |
|||
else |
|||
{ |
|||
logger.Error($"请求变更出价接口失败,返回消息:{res?.Content?.ReadAsStringAsync()?.Result}, 店铺id:{trusteeshipTask.ShopId},请求参数{postData}"); |
|||
} |
|||
Thread.Sleep(500); |
|||
|
|||
} |
|||
await update.ExecuteUpdatedAsync(); |
|||
|
|||
if (AdjustLogList.Any()) |
|||
await fsql.Insert<Sbf_AdjustLog>(AdjustLogList).ExecuteInsertedAsync(); |
|||
|
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 降低出价策略
|
|||
/// </summary>
|
|||
/// <returns></returns>
|
|||
/// <exception cref="NotImplementedException"></exception>
|
|||
public async Task RunGrowthPeriodLowerBidPriceTrusteeshipPolicy() |
|||
{ |
|||
var searchTrusteeshipTaskList = OverFirstWeekUpdateTrusteeshipPolicyData();//获取两周的数据
|
|||
|
|||
|
|||
|
|||
List<Sbf_AdjustLog> AdjustLogList = new List<Sbf_AdjustLog>(); |
|||
var hour = DateTime.Now.Hour; |
|||
|
|||
List<Sbf_AdjustLog> historyAdjustLogList = new List<Sbf_AdjustLog>(); |
|||
if (hour != 12) |
|||
{ |
|||
//获取当天的降低出价日志记录
|
|||
|
|||
historyAdjustLogList = fsql.Select<Sbf_AdjustLog>().Where(l => l.CreateTime.Value.Date == DateTime.Now.Date && l.PolicyType == Model.Enums.PolicyType.成长期策略包 |
|||
&& l.AdjustType == Model.Enums.AdjustType.出价 && l.AdjustWay == Model.Enums.AdjustWay.降低).ToList(); |
|||
} |
|||
|
|||
var update = fsql.Update<Sbf_TrusteeshipTask>(); |
|||
foreach (var trusteeshipTask in searchTrusteeshipTaskList) |
|||
{ |
|||
if (trusteeshipTask.BidPrice == null || trusteeshipTask.BidPrice == 0) |
|||
{ |
|||
logger.Error($"出价未获取,或者获取的出价为0,店铺id:{trusteeshipTask.ShopId},任务Id{trusteeshipTask.Id}"); |
|||
continue; |
|||
} |
|||
if (trusteeshipTask.Budget == null || trusteeshipTask.Budget == 0) |
|||
{ |
|||
logger.Error($"预算未获取,或者获取的预算为0,店铺id:{trusteeshipTask.ShopId},任务Id{trusteeshipTask.Id}"); |
|||
continue; |
|||
} |
|||
if (trusteeshipTask.Budget == trusteeshipTask.NowCost)//花费耗尽
|
|||
{ |
|||
decimal newBidPrice = 0m; |
|||
string adjustContent = string.Empty; |
|||
if (hour == 12)//预算早于12:00前花完 降低出价30%
|
|||
{ |
|||
newBidPrice = Math.Round(trusteeshipTask.BidPrice.Value * (1 - 0.3m), 2); |
|||
adjustContent = "降低出价30%"; |
|||
} |
|||
else if (hour == 18)//预算早于12:00前花完 降低出价20%
|
|||
{ |
|||
if (historyAdjustLogList.Any(h => h.TrusteeshipTaskId == trusteeshipTask.Id))//当天已经降低出价过
|
|||
continue; |
|||
|
|||
adjustContent = "降低出价20%"; |
|||
newBidPrice = Math.Round(trusteeshipTask.BidPrice.Value * (1 - 0.2m), 2); |
|||
} |
|||
else if (hour == 23)//预算早于12:00前花完 降低出价10%
|
|||
{ |
|||
if (historyAdjustLogList.Any(h => h.TrusteeshipTaskId == trusteeshipTask.Id))//当天已经降低出价过
|
|||
continue; |
|||
adjustContent = "降低出价10%"; |
|||
newBidPrice = Math.Round(trusteeshipTask.BidPrice.Value * (1 - 0.1m), 2); |
|||
} |
|||
else |
|||
{//出错
|
|||
continue; |
|||
} |
|||
decimal oldBidPrice = trusteeshipTask.BidPrice.Value; |
|||
|
|||
trusteeshipTask.BidPrice = newBidPrice;//表里更新 新的出价
|
|||
update.Where(u => u.Id == trusteeshipTask.Id).Set(u => u.BidPrice, newBidPrice); |
|||
//更新快车的 出价
|
|||
string url = "http://txapi.sbf.qiyue666.com/SanBanFu/Api/SendFeeUpdate"; |
|||
HttpClient client = new HttpClient(); |
|||
client.Timeout = TimeSpan.FromMinutes(1); |
|||
|
|||
var postData = JsonConvert.SerializeObject(new |
|||
{ |
|||
ShopId = trusteeshipTask.ShopId?.ToString(), |
|||
AdgroupId = trusteeshipTask.AdGroupId?.ToString(), |
|||
SearchFee = newBidPrice |
|||
|
|||
}); |
|||
|
|||
HttpContent content = new StringContent(postData); |
|||
|
|||
var res = await client.PostAsync(url, content); |
|||
if (res.IsSuccessStatusCode) |
|||
{ |
|||
//发送成功
|
|||
logger.Info($"请求变更出价接口成功! 店铺id:{trusteeshipTask.ShopId},请求参数{postData}"); |
|||
|
|||
AdjustLogList.Add(new Sbf_AdjustLog |
|||
{ |
|||
AdjustType = Model.Enums.AdjustType.出价, |
|||
AdjustWay = Model.Enums.AdjustWay.调高, |
|||
CreateTime = DateTime.Now, |
|||
PolicyType = Model.Enums.PolicyType.成长期策略包, |
|||
TrusteeshipTaskId = trusteeshipTask.Id, |
|||
OperateContent = $"{adjustContent},原出价:{oldBidPrice},调整后出价:{newBidPrice}" |
|||
}); |
|||
|
|||
} |
|||
else |
|||
{ |
|||
logger.Error($"请求变更出价接口失败,返回消息:{res?.Content?.ReadAsStringAsync()?.Result}, 店铺id:{trusteeshipTask.ShopId},请求参数{postData}"); |
|||
} |
|||
Thread.Sleep(500); |
|||
|
|||
} |
|||
} |
|||
await update.ExecuteAffrowsAsync(); |
|||
if (AdjustLogList.Any()) |
|||
await fsql.Insert<Sbf_AdjustLog>(AdjustLogList).ExecuteInsertedAsync(); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,52 @@ |
|||
using FreeSql.DataAnnotations; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace SBF.Model.Db.Trusteeship |
|||
{ |
|||
public class Sbf_AdjustLog |
|||
{ |
|||
[Column(DbType = "bigint", IsPrimary = true)] |
|||
public long Id { get; set; } |
|||
|
|||
|
|||
/// <summary>
|
|||
/// 托管任务Id
|
|||
/// </summary>
|
|||
[Column(DbType = "bigint")] |
|||
public long TrusteeshipTaskId { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 创建时间
|
|||
/// </summary>
|
|||
[Column(DbType = "datetime")] |
|||
public DateTime? CreateTime { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 策略类型 成长期策略包 = 0, 冲击主力策略包 = 1, 稳定期策略包 = 2, 主力期策略包 = 3
|
|||
/// </summary>
|
|||
[Column(MapType = typeof(int?))] |
|||
public Enums.PolicyType? PolicyType { get; set; } = Enums.PolicyType.成长期策略包; |
|||
|
|||
/// <summary>
|
|||
/// 调整类型(出价=0,预算=1)
|
|||
/// </summary>
|
|||
[Column(MapType = typeof(int?))] |
|||
public Enums.AdjustType AdjustType { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 调整方式(调高 = 0, 降低 = 1, 指定值 = 2)
|
|||
/// </summary>
|
|||
[Column(MapType = typeof(int?))] |
|||
public Enums.AdjustWay AdjustWay { get; set; } |
|||
|
|||
|
|||
/// <summary>
|
|||
/// 操作内容
|
|||
/// </summary>
|
|||
public string OperateContent { get; set; } |
|||
} |
|||
} |
@ -0,0 +1,60 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace SBF.Model.Dto |
|||
{ |
|||
public class BatchUpdateBidPriceRequest |
|||
{ |
|||
/* [{AdgroupId:'',SearchFee:0,End:2022-01-01,Start:2022-01-01,ShopId:123,TotalCost:1,RenQunCost:1,KeyWordCost:1,ShopCost:1}] */ |
|||
|
|||
/// <summary>
|
|||
/// 单元Id
|
|||
/// </summary>
|
|||
public string AdgroupId { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 出价
|
|||
/// </summary>
|
|||
public decimal SearchFee { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 开始时间
|
|||
/// </summary>
|
|||
public DateTime? Start { get; set; } |
|||
/// <summary>
|
|||
/// 结束时间
|
|||
/// </summary>
|
|||
public DateTime? End { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 店铺id
|
|||
/// </summary>
|
|||
public long ShopId { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 单元总花费
|
|||
/// </summary>
|
|||
public decimal TotalCost { get; set; } |
|||
|
|||
|
|||
/// <summary>
|
|||
/// 人群花费
|
|||
/// </summary>
|
|||
public decimal? RenQunCost { get; set; } |
|||
|
|||
|
|||
/// <summary>
|
|||
/// 关键词花费
|
|||
/// </summary>
|
|||
public decimal? KeyWordCost { get; set; } |
|||
|
|||
|
|||
/// <summary>
|
|||
/// 店铺商品花费
|
|||
/// </summary>
|
|||
public decimal? ShopCost { get; set; } |
|||
} |
|||
} |
@ -0,0 +1,43 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace SBF.Model.Dto |
|||
{ |
|||
public class BatchUpdateBudgetRequest |
|||
{ |
|||
|
|||
/* {CampaignId:'',Budget:0,End:2022-01-01,Start:2022-01-01,ShopId:123,TotalCost:1} */ |
|||
|
|||
/// <summary>
|
|||
/// 计划Id
|
|||
/// </summary>
|
|||
public string CampaignId { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 预算
|
|||
/// </summary>
|
|||
public decimal? Budget { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 开始时间
|
|||
/// </summary>
|
|||
public DateTime? Start { get; set; } |
|||
/// <summary>
|
|||
/// 结束时间
|
|||
/// </summary>
|
|||
public DateTime? End { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 店铺id
|
|||
/// </summary>
|
|||
public long? ShopId { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// 计划总花费
|
|||
/// </summary>
|
|||
public decimal? TotalCost { get; set; } |
|||
} |
|||
} |
Loading…
Reference in new issue