diff --git a/BBWY.Server.API/Controllers/JDReportFormStatisticsController.cs b/BBWY.Server.API/Controllers/JDReportFormStatisticsController.cs
new file mode 100644
index 00000000..cb66fd43
--- /dev/null
+++ b/BBWY.Server.API/Controllers/JDReportFormStatisticsController.cs
@@ -0,0 +1,52 @@
+using BBWY.Server.Business.Statistics;
+using BBWY.Server.Model.Dto;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using System.Collections.Generic;
+
+namespace BBWY.Server.API.Controllers
+{
+
+ public class JDReportFormStatisticsController : BaseApiController
+ {
+ private JDReportFormStatisticsBusiness jDReportFormStatisticsBusiness;
+
+ public JDReportFormStatisticsController(IHttpContextAccessor httpContextAccessor, JDReportFormStatisticsBusiness jDReportFormStatisticsBusiness) : base(httpContextAccessor)
+ {
+ this.jDReportFormStatisticsBusiness = jDReportFormStatisticsBusiness;
+ }
+
+ ///
+ /// 计划维度GOI计算,支持快车和京速推
+ ///
+ ///
+ ///
+ [HttpPost]
+ public IList CalculationCampaignLevelGOI([FromBody]GOIRequest gOIRequest)
+ {
+ return jDReportFormStatisticsBusiness.CalculationCampaignLevelGOI(gOIRequest);
+ }
+
+ ///
+ /// 单元维度GOI计算,仅支持快车
+ ///
+ ///
+ ///
+ [HttpPost]
+ public IList CalculationAdGroupLevelGOI([FromBody] GOIRequest gOIRequest)
+ {
+ return jDReportFormStatisticsBusiness.CalculationAdGroupLevelGOI(gOIRequest);
+ }
+
+ ///
+ /// 创意维度GOI计算,仅支持快车
+ ///
+ ///
+ ///
+ [HttpPost]
+ public IList CalculationAdLevelGOI([FromBody] GOIRequest gOIRequest)
+ {
+ return jDReportFormStatisticsBusiness.CalculationAdLevelGOI(gOIRequest);
+ }
+ }
+}
diff --git a/BBWY.Server.Business/Statistics/JDReportFormStatisticsBusiness.cs b/BBWY.Server.Business/Statistics/JDReportFormStatisticsBusiness.cs
new file mode 100644
index 00000000..8df02de0
--- /dev/null
+++ b/BBWY.Server.Business/Statistics/JDReportFormStatisticsBusiness.cs
@@ -0,0 +1,307 @@
+using BBWY.Common.Models;
+using BBWY.Server.Model.Db;
+using BBWY.Server.Model.Dto;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Yitter.IdGenerator;
+
+namespace BBWY.Server.Business.Statistics
+{
+ public class JDReportFormStatisticsBusiness : BaseBusiness, IDenpendency
+ {
+ public JDReportFormStatisticsBusiness(IFreeSql fsql, NLog.ILogger logger, IIdGenerator idGenerator) : base(fsql, logger, idGenerator)
+ {
+
+ }
+
+ public IList CalculationCampaignLevelGOI(GOIRequest gOIRequest)
+ {
+ var _7dEndDate = DateTime.Now.Date.AddDays(-1);
+ var _7dStartDate = _7dEndDate.AddDays(-6);
+ var _7dEndTime = _7dEndDate.AddDays(1).AddSeconds(-1);
+
+ var _30dEndDate = DateTime.Now.Date.AddDays(-1);
+ var _30dStartDate = _30dEndDate.AddDays(-29);
+ var _30dEndTime = _30dEndDate.AddDays(1).AddSeconds(-1);
+
+ var customEndTime = gOIRequest.EndDate.AddDays(1).AddSeconds(-1);
+
+ var _7dCampaignCosts = fsql.Select().Where(x => gOIRequest.LevelIdList.Contains(x.CampaignId.Value) &&
+ x.Date >= _7dStartDate &&
+ x.Date <= _7dEndDate)
+ .GroupBy(x => x.CampaignId)
+ .ToList(g => new
+ {
+ Cost = g.Sum(g.Value.Cost),
+ CampaignId = g.Key
+ });
+
+ var _7dCampaignProfits = fsql.Select().InnerJoin((jr, oc) => jr.OrderId == oc.OrderId)
+ .Where((jr, oc) => gOIRequest.LevelIdList.Contains(jr.CampaignId.Value) &&
+ jr.OrderTime >= _7dStartDate &&
+ jr.OrderTime <= _7dEndTime)
+ .GroupBy((jr, oc) => jr.CampaignId)
+ .ToList(g => new
+ {
+ CampaignId = g.Key,
+ Profit = g.Sum(g.Value.Item2.Profit)
+ });
+
+ var _30dCampaignCosts = fsql.Select().Where(x => gOIRequest.LevelIdList.Contains(x.CampaignId.Value) &&
+ x.Date >= _30dStartDate &&
+ x.Date <= _30dEndDate)
+ .GroupBy(x => x.CampaignId)
+ .ToList(g => new
+ {
+ Cost = g.Sum(g.Value.Cost),
+ CampaignId = g.Key
+ });
+
+ var _30dCampaignProfits = fsql.Select().InnerJoin((jr, oc) => jr.OrderId == oc.OrderId)
+ .Where((jr, oc) => gOIRequest.LevelIdList.Contains(jr.CampaignId.Value) &&
+ jr.OrderTime >= _30dStartDate &&
+ jr.OrderTime <= _30dEndTime)
+ .GroupBy((jr, oc) => jr.CampaignId)
+ .ToList(g => new
+ {
+ CampaignId = g.Key,
+ Profit = g.Sum(g.Value.Item2.Profit)
+ });
+
+ var customDaysCampaignCosts = fsql.Select().Where(x => gOIRequest.LevelIdList.Contains(x.CampaignId.Value) &&
+ x.Date >= gOIRequest.StartDate &&
+ x.Date <= gOIRequest.EndDate)
+ .GroupBy(x => x.CampaignId)
+ .ToList(g => new
+ {
+ Cost = g.Sum(g.Value.Cost),
+ CampaignId = g.Key
+ });
+
+ var customDaysCampaignProfits = fsql.Select().InnerJoin((jr, oc) => jr.OrderId == oc.OrderId)
+ .Where((jr, oc) => gOIRequest.LevelIdList.Contains(jr.CampaignId.Value) &&
+ jr.OrderTime >= gOIRequest.StartDate &&
+ jr.OrderTime <= customEndTime)
+ .GroupBy((jr, oc) => jr.CampaignId)
+ .ToList(g => new
+ {
+ CampaignId = g.Key,
+ Profit = g.Sum(g.Value.Item2.Profit)
+ });
+
+ var list = new List();
+ foreach (var levelId in gOIRequest.LevelIdList)
+ {
+ var goiResponse = new JDMultiLevelGOIResponse()
+ {
+ LevelId = levelId,
+ BusinessType = gOIRequest.BusinessType
+ };
+ goiResponse._7GOI.Cost = _7dCampaignCosts.FirstOrDefault(x => x.CampaignId == levelId)?.Cost ?? 0M;
+ goiResponse._7GOI.Profit = _7dCampaignProfits.FirstOrDefault(x => x.CampaignId == levelId)?.Profit ?? 0M;
+
+ goiResponse._30GOI.Cost = _30dCampaignCosts.FirstOrDefault(x => x.CampaignId == levelId)?.Cost ?? 0M;
+ goiResponse._30GOI.Profit = _30dCampaignProfits.FirstOrDefault(x => x.CampaignId == levelId)?.Profit ?? 0M;
+
+ goiResponse.CustomDaysGOI.Cost = customDaysCampaignCosts.FirstOrDefault(x => x.CampaignId == levelId)?.Cost ?? 0M;
+ goiResponse.CustomDaysGOI.Profit = customDaysCampaignProfits.FirstOrDefault(x => x.CampaignId == levelId)?.Profit ?? 0M;
+ list.Add(goiResponse);
+ }
+ return list;
+ }
+
+ 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 _30dEndDate = DateTime.Now.Date.AddDays(-1);
+ var _30dStartDate = _30dEndDate.AddDays(-29);
+ var _30dEndTime = _30dEndDate.AddDays(1).AddSeconds(-1);
+
+ var customEndTime = gOIRequest.EndDate.AddDays(1).AddSeconds(-1);
+
+ var _7dAdGroupCosts = fsql.Select().Where(x => gOIRequest.LevelIdList.Contains(x.AdGroupId.Value) &&
+ x.Date >= _7dStartDate &&
+ x.Date <= _7dEndDate)
+ .GroupBy(x => x.AdGroupId)
+ .ToList(g => new
+ {
+ Cost = g.Sum(g.Value.Cost),
+ AdGroupId = g.Key
+ });
+
+ var _7dAdGroupProfits = fsql.Select().InnerJoin((jr, oc) => jr.OrderId == oc.OrderId)
+ .Where((jr, oc) => gOIRequest.LevelIdList.Contains(jr.AdGroupId.Value) &&
+ jr.OrderTime >= _7dStartDate &&
+ jr.OrderTime <= _7dEndTime)
+ .GroupBy((jr, oc) => jr.AdGroupId)
+ .ToList(g => new
+ {
+ AdGroupId = g.Key,
+ Profit = g.Sum(g.Value.Item2.Profit)
+ });
+
+ var _30dAdGroupCosts = fsql.Select().Where(x => gOIRequest.LevelIdList.Contains(x.AdGroupId.Value) &&
+ x.Date >= _30dStartDate &&
+ x.Date <= _30dEndDate)
+ .GroupBy(x => x.AdGroupId)
+ .ToList(g => new
+ {
+ Cost = g.Sum(g.Value.Cost),
+ AdGroupId = g.Key
+ });
+
+ var _30dAdGroupProfits = fsql.Select().InnerJoin((jr, oc) => jr.OrderId == oc.OrderId)
+ .Where((jr, oc) => gOIRequest.LevelIdList.Contains(jr.AdGroupId.Value) &&
+ jr.OrderTime >= _30dStartDate &&
+ jr.OrderTime <= _30dEndTime)
+ .GroupBy((jr, oc) => jr.AdGroupId)
+ .ToList(g => new
+ {
+ AdGroupId = g.Key,
+ Profit = g.Sum(g.Value.Item2.Profit)
+ });
+
+ var customDaysAdGroupCosts = fsql.Select().Where(x => gOIRequest.LevelIdList.Contains(x.AdGroupId.Value) &&
+ x.Date >= gOIRequest.StartDate &&
+ x.Date <= gOIRequest.EndDate)
+ .GroupBy(x => x.AdGroupId)
+ .ToList(g => new
+ {
+ Cost = g.Sum(g.Value.Cost),
+ AdGroupId = g.Key
+ });
+
+ var customDaysAdGroupProfits = fsql.Select().InnerJoin((jr, oc) => jr.OrderId == oc.OrderId)
+ .Where((jr, oc) => gOIRequest.LevelIdList.Contains(jr.AdGroupId.Value) &&
+ jr.OrderTime >= gOIRequest.StartDate &&
+ jr.OrderTime <= customEndTime)
+ .GroupBy((jr, oc) => jr.AdGroupId)
+ .ToList(g => new
+ {
+ AdGroupId = g.Key,
+ Profit = g.Sum(g.Value.Item2.Profit)
+ });
+
+ var list = new List();
+ foreach (var levelId in gOIRequest.LevelIdList)
+ {
+ var goiResponse = new JDMultiLevelGOIResponse()
+ {
+ 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._30GOI.Cost = _30dAdGroupCosts.FirstOrDefault(x => x.AdGroupId == levelId)?.Cost ?? 0M;
+ goiResponse._30GOI.Profit = _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;
+ list.Add(goiResponse);
+ }
+ return list;
+ }
+
+ 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 _30dEndDate = DateTime.Now.Date.AddDays(-1);
+ var _30dStartDate = _30dEndDate.AddDays(-29);
+ var _30dEndTime = _30dEndDate.AddDays(1).AddSeconds(-1);
+
+ var customEndTime = gOIRequest.EndDate.AddDays(1).AddSeconds(-1);
+
+ var _7dAdCosts = fsql.Select().Where(x => gOIRequest.LevelIdList.Contains(x.AdId.Value) &&
+ x.Date >= _7dStartDate &&
+ x.Date <= _7dEndDate)
+ .GroupBy(x => x.AdId)
+ .ToList(g => new
+ {
+ Cost = g.Sum(g.Value.Cost),
+ AdId = g.Key
+ });
+
+ var _7dAdProfits = fsql.Select().InnerJoin((jr, oc) => jr.OrderId == oc.OrderId)
+ .Where((jr, oc) => gOIRequest.LevelIdList.Contains(jr.AdId.Value) &&
+ jr.OrderTime >= _7dStartDate &&
+ jr.OrderTime <= _7dEndTime)
+ .GroupBy((jr, oc) => jr.AdId)
+ .ToList(g => new
+ {
+ AdId = g.Key,
+ Profit = g.Sum(g.Value.Item2.Profit)
+ });
+
+ var _30dAdCosts = fsql.Select().Where(x => gOIRequest.LevelIdList.Contains(x.AdId.Value) &&
+ x.Date >= _30dStartDate &&
+ x.Date <= _30dEndDate)
+ .GroupBy(x => x.AdId)
+ .ToList(g => new
+ {
+ Cost = g.Sum(g.Value.Cost),
+ AdId = g.Key
+ });
+
+ var _30dAdProfits = fsql.Select().InnerJoin((jr, oc) => jr.OrderId == oc.OrderId)
+ .Where((jr, oc) => gOIRequest.LevelIdList.Contains(jr.AdId.Value) &&
+ jr.OrderTime >= _30dStartDate &&
+ jr.OrderTime <= _30dEndTime)
+ .GroupBy((jr, oc) => jr.AdId)
+ .ToList(g => new
+ {
+ AdId = g.Key,
+ Profit = g.Sum(g.Value.Item2.Profit)
+ });
+
+ var customDaysAdCosts = fsql.Select().Where(x => gOIRequest.LevelIdList.Contains(x.AdId.Value) &&
+ x.Date >= gOIRequest.StartDate &&
+ x.Date <= gOIRequest.EndDate)
+ .GroupBy(x => x.AdId)
+ .ToList(g => new
+ {
+ Cost = g.Sum(g.Value.Cost),
+ AdId = g.Key
+ });
+
+ var customDaysAdProfits = fsql.Select().InnerJoin((jr, oc) => jr.OrderId == oc.OrderId)
+ .Where((jr, oc) => gOIRequest.LevelIdList.Contains(jr.AdId.Value) &&
+ jr.OrderTime >= gOIRequest.StartDate &&
+ jr.OrderTime <= customEndTime)
+ .GroupBy((jr, oc) => jr.AdId)
+ .ToList(g => new
+ {
+ AdId = g.Key,
+ Profit = g.Sum(g.Value.Item2.Profit)
+ });
+
+ var list = new List();
+ foreach (var levelId in gOIRequest.LevelIdList)
+ {
+ var goiResponse = new JDMultiLevelGOIResponse()
+ {
+ 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._30GOI.Cost = _30dAdCosts.FirstOrDefault(x => x.AdId == levelId)?.Cost ?? 0M;
+ goiResponse._30GOI.Profit = _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;
+ list.Add(goiResponse);
+ }
+ return list;
+ }
+ }
+}
diff --git a/BBWY.Server.Model/Dto/Request/Statistics/GOIRequest.cs b/BBWY.Server.Model/Dto/Request/Statistics/GOIRequest.cs
new file mode 100644
index 00000000..885c6008
--- /dev/null
+++ b/BBWY.Server.Model/Dto/Request/Statistics/GOIRequest.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BBWY.Server.Model.Dto
+{
+ public class GOIRequest
+ {
+ ///
+ /// 维度Id数组
+ ///
+ public IList LevelIdList { get; set; }
+
+ ///
+ /// 业务线 快车=2,京速推=134217728
+ /// 计划维度支持快车,京速推
+ /// 单元维度仅支持快车
+ /// 创意维度仅支持快车
+ /// SKU维度仅支持京速推
+ ///
+ public int BusinessType { get; set; }
+
+ public DateTime StartDate { get; set; }
+
+ public DateTime EndDate { get; set; }
+ }
+
+ public class SkuGOIRequest: GOIRequest
+ {
+ public new IList LevelIdList { get; set; }
+ }
+}
diff --git a/BBWY.Server.Model/Dto/Response/Statistics/JDReportForm/GOIResponse.cs b/BBWY.Server.Model/Dto/Response/Statistics/JDReportForm/GOIResponse.cs
new file mode 100644
index 00000000..9391475f
--- /dev/null
+++ b/BBWY.Server.Model/Dto/Response/Statistics/JDReportForm/GOIResponse.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace BBWY.Server.Model.Dto
+{
+ public class GOIResponse
+ {
+ public decimal Cost { get; set; }
+
+ public decimal Profit { get; set; }
+
+ public decimal GOI
+ {
+ get
+ {
+ return Cost == 0M ? 0M : Math.Round(Profit / Cost, 2);
+ }
+ }
+ }
+}
diff --git a/BBWY.Server.Model/Dto/Response/Statistics/JDReportForm/JDMultiLevelGOIResponse.cs b/BBWY.Server.Model/Dto/Response/Statistics/JDReportForm/JDMultiLevelGOIResponse.cs
new file mode 100644
index 00000000..a3b56ca3
--- /dev/null
+++ b/BBWY.Server.Model/Dto/Response/Statistics/JDReportForm/JDMultiLevelGOIResponse.cs
@@ -0,0 +1,25 @@
+namespace BBWY.Server.Model.Dto
+{
+ public class JDMultiLevelGOIResponse
+ {
+ public JDMultiLevelGOIResponse()
+ {
+ _7GOI = new GOIResponse();
+ _30GOI = new GOIResponse();
+ CustomDaysGOI = new GOIResponse();
+ }
+
+ public long LevelId { get; set; }
+
+ ///
+ /// 快车=2 京速推=134217728
+ ///
+ public int BusinessType { get; set; }
+
+ public GOIResponse _7GOI { get; set; }
+
+ public GOIResponse _30GOI { get; set; }
+
+ public GOIResponse CustomDaysGOI { get; set; }
+ }
+}