diff --git a/SiNan.Business/AggregationBusiness.cs b/SiNan.Business/AggregationBusiness.cs index e435197..407127c 100644 --- a/SiNan.Business/AggregationBusiness.cs +++ b/SiNan.Business/AggregationBusiness.cs @@ -3,6 +3,7 @@ using SiNan.Common.Log; using SiNan.Common.Models; using SiNan.Model; using SiNan.Model.Core; +using SiNan.Model.Core.ROI; using SiNan.Model.Db; using SiNan.Model.Dto; using Yitter.IdGenerator; @@ -192,10 +193,15 @@ namespace SiNan.Business var aggregationDate_ProductLevelList = goiBusiness.StatisticsProductLevelGOI(currentGroupSkuIdList, startDate_aggregationDate, endDate_aggregationDate); var aggregationDate_PopularizeLevelList = goiBusiness.StatisticsPopularizeLevelGOI(currentGroupSkuIdList, startDate_aggregationDate, endDate_aggregationDate); var aggregationDate_SkuActualAmountList = StatisticsActualAmountBySku(currentGroupSkuIdList, startDate_aggregationDate, endDate_aggregationDate); + var aggregationDate_PopularizeLevelROIList = goiBusiness.StatisticsPopluarizeLvelROI(currentGroupSkuIdList, startDate_aggregationDate, endDate_aggregationDate); + + var aggregationDate_DirectPopularizeLevelROIList = goiBusiness.StatisticsPopluarizeLvelROI(currentGroupSkuIdList, startDate_aggregationDate, endDate_aggregationDate, true); + IList recent7d_ProductLevelList = null; IList recent7d_PopularizeLevelList = null; IList recent30d_ProductLevelList = null; IList recent30d_PopularizeLevelList = null; + IList recent7d_PopluarizeLevelROIList = null; if (isLastDate && (DateTime.Now.Date - startDate_aggregationDate).TotalDays <= 31) @@ -211,6 +217,7 @@ namespace SiNan.Business recent7d_PopularizeLevelList = goiBusiness.StatisticsPopularizeLevelGOI(currentGroupSkuIdList, startDate_Recent7day, endDate_Recent7day); recent30d_ProductLevelList = goiBusiness.StatisticsProductLevelGOI(currentGroupSkuIdList, startDate_Recent30day, endDate_Recent30day); ; recent30d_PopularizeLevelList = goiBusiness.StatisticsPopularizeLevelGOI(currentGroupSkuIdList, startDate_Recent30day, endDate_Recent30day); + recent7d_PopluarizeLevelROIList = goiBusiness.StatisticsPopluarizeLvelROI(currentGroupSkuIdList, startDate_Recent7day, endDate_Recent7day); } foreach (var spuId in spuGroup) @@ -223,6 +230,8 @@ namespace SiNan.Business IList currentSpu_Recent30d_ProductLevelList = recent30d_ProductLevelList?.Where(x => currentSpuSkuIdList.Contains(x.Sku)).ToList(); IList currentSpu_Recent30d_PopularizeLevelList = recent30d_PopularizeLevelList?.Where(x => currentSpuSkuIdList.Contains(x.Sku)).ToList(); + //var currentSpu_AggregationDate_PopularizeLevelROIList = aggregationDate_PopularizeLevelROIList.Where(x => currentSpuSkuIdList.Contains(x.Sku)).ToList(); + #region 处理SPU每日聚合 var spugoi_AggregationDate_ProductLevel = new GOIBySpu() { @@ -339,10 +348,13 @@ namespace SiNan.Business #region 处理SKU每日聚合 var skugoi_AggregationDate_ProductLevel = currentSpu_AggregationDate_ProductLevelList.FirstOrDefault(x => x.Sku == skuId); var skugoi_AggregationDate_PopularizeLevel = currentSpu_AggregationDate_PopularizeLevelList.FirstOrDefault(x => x.Sku == skuId); + var skuroi_aggregationDate_PopularizeLevelROI = aggregationDate_PopularizeLevelROIList.FirstOrDefault(x => x.Sku == skuId); + var skuroi_aggregationDate_DirectPopularizeLevelROI = aggregationDate_DirectPopularizeLevelROIList.FirstOrDefault(x => x.Sku == skuId); var skugoi_Recent7d_ProductLevel = currentSpu_Recent7d_ProductLevelList?.FirstOrDefault(x => x.Sku == skuId); var skugoi_Recent7d_PopularizeLevel = currentSpu_Recent7d_PopularizeLevelList?.FirstOrDefault(x => x.Sku == skuId); var skugoi_Recent30d_ProductLevel = currentSpu_Recent30d_ProductLevelList?.FirstOrDefault(x => x.Sku == skuId); var skugoi_Recent30d_PopularizeLevel = currentSpu_Recent30d_PopularizeLevelList?.FirstOrDefault(x => x.Sku == skuId); + var skuroi_Recent7d_PopularizeLevel = recent7d_PopluarizeLevelROIList?.FirstOrDefault(x => x.Sku == skuId); var skuDailyAggregation = new AggregationJDPopularizeSkuDaily() { @@ -357,7 +369,11 @@ namespace SiNan.Business ProductLevelGOI = skugoi_AggregationDate_ProductLevel?.GOI ?? 0M, PopularizeLevelProfit = skugoi_AggregationDate_PopularizeLevel?.Profit ?? 0M, PopularizeLevelGOI = skugoi_AggregationDate_PopularizeLevel?.GOI ?? 0M, - ActualAmount = aggregationDate_SkuActualAmountList.FirstOrDefault(x => x.Sku == skuId)?.ActualAmount ?? 0M + ActualAmount = aggregationDate_SkuActualAmountList.FirstOrDefault(x => x.Sku == skuId)?.ActualAmount ?? 0M, + PopularizeAmount = skuroi_aggregationDate_PopularizeLevelROI?.Amount ?? 0M, + PopularizeLevelROI = skuroi_aggregationDate_PopularizeLevelROI?.ROI ?? 0M, + DirectPopularizeAmount = skuroi_aggregationDate_DirectPopularizeLevelROI?.Amount ?? 0M, + DirectPopularizeLevelROI = skuroi_aggregationDate_DirectPopularizeLevelROI?.ROI ?? 0M }; insertAggregationSkuDailyList.Add(skuDailyAggregation); #endregion @@ -387,7 +403,8 @@ namespace SiNan.Business Recent30dProductLevelProfit = skugoi_Recent30d_ProductLevel?.Profit ?? 0M, Recent30dProductLevelGOI = skugoi_Recent30d_ProductLevel?.GOI ?? 0M, Recent30dPopularizeLevelProfit = skugoi_Recent30d_PopularizeLevel?.Profit ?? 0M, - Recent30dPopularizeLevelGOI = skugoi_Recent30d_PopularizeLevel?.GOI ?? 0M + Recent30dPopularizeLevelGOI = skugoi_Recent30d_PopularizeLevel?.GOI ?? 0M, + Recent7dPopularizeLevelROI = skuroi_Recent7d_PopularizeLevel?.ROI ?? 0M }); } else @@ -831,7 +848,10 @@ namespace SiNan.Business List insertAggregationAdSkuDailyList = new List(); var aggregationDate_PopularizeLevelList = goiBusiness.CalculationAdSkuLevelGOI(adSkuIdList, startDate_aggregationDate, endDate_aggregationDate); var aggregationDate_ProductLevelList = goiBusiness.CalculationAdSkuProductLevelGOI(adSkuIdList, startDate_aggregationDate, endDate_aggregationDate); - var aggregationDate_SkuPopularizeAmountList = StatisticsPopularizeAmountBySku(adSkuIdList, startDate_aggregationDate, endDate_aggregationDate); + //var aggregationDate_SkuPopularizeAmountList = StatisticsPopularizeAmountBySku(adSkuIdList, startDate_aggregationDate, endDate_aggregationDate); + var aggregationDate_PopularizeLevelROIList = goiBusiness.StatisticsAdSkuLvelROI(adSkuIdList, startDate_aggregationDate, endDate_aggregationDate); + + var aggregationDate_DirectPopularizeLevelROIList = goiBusiness.StatisticsAdSkuLvelROI(adSkuIdList, startDate_aggregationDate, endDate_aggregationDate, true); var adSkuIndex = 0; foreach (var adSku in adSkuList) @@ -845,9 +865,14 @@ namespace SiNan.Business x.CampaignId == adSku.CampaignId); var adSkuGoi_AggregationDate_ProductLevel = aggregationDate_ProductLevelList.FirstOrDefault(x => x.Sku == adSku.Sku && x.BusinessType == adSku.BusinessType); - var adSkuPoplarizeAmount = aggregationDate_SkuPopularizeAmountList.FirstOrDefault(x => x.Sku == adSku.Sku && - x.BusinessType == adSku.BusinessType && - x.CampaignId == adSku.CampaignId); + //var adSkuPoplarizeAmount = aggregationDate_SkuPopularizeAmountList.FirstOrDefault(x => x.Sku == adSku.Sku && x.BusinessType == adSku.BusinessType && x.CampaignId == adSku.CampaignId); + var adSkuPopularizeROI = aggregationDate_PopularizeLevelROIList.FirstOrDefault(x => x.Sku == adSku.Sku && + x.BusinessType == adSku.BusinessType && + x.CampaignId == adSku.CampaignId); + + var adSkuDirectPopularizeROI = aggregationDate_DirectPopularizeLevelROIList.FirstOrDefault(x => x.Sku == adSku.Sku && + x.BusinessType == adSku.BusinessType && + x.CampaignId == adSku.CampaignId); var adSkuDailyAggregation = new AggregationJDPopularizeAdSkuDaily() { @@ -865,8 +890,11 @@ namespace SiNan.Business BusinessType = adSku.BusinessType, SkuId = adSku.Sku, AdId = adSku.AdId, - PopularizeAmount = adSkuPoplarizeAmount?.ActualAmount ?? 0M, - Clicks = adSkuGoi_AggregationDate_PopularizeLevel?.Clicks ?? 0 + Clicks = adSkuGoi_AggregationDate_PopularizeLevel?.Clicks ?? 0, + PopularizeAmount = adSkuPopularizeROI?.Amount ?? 0M, + PopularizeLevelROI = adSkuPopularizeROI?.ROI ?? 0M, + DirectPopularizeAmount = adSkuDirectPopularizeROI?.Amount ?? 0M, + DirectPopularizeLevelROI = adSkuDirectPopularizeROI?.ROI ?? 0M }; insertAggregationAdSkuDailyList.Add(adSkuDailyAggregation); diff --git a/SiNan.Business/GOIBusiness.cs b/SiNan.Business/GOIBusiness.cs index c705f3a..a64100b 100644 --- a/SiNan.Business/GOIBusiness.cs +++ b/SiNan.Business/GOIBusiness.cs @@ -6,6 +6,7 @@ using SiNan.Common.Log; using SiNan.Common.Models; using SiNan.Model; using SiNan.Model.Core; +using SiNan.Model.Core.ROI; using SiNan.Model.Db; using SiNan.Model.Dto; using Yitter.IdGenerator; @@ -57,7 +58,7 @@ namespace SiNan.Business return list; } - public IList StatisticsPopularizeLevelGOI(IList skuIdList, DateTime? startDate, DateTime? endDate) + public IList StatisticsPopularizeLevelGOI(IList skuIdList, DateTime? startDate, DateTime? endDate, bool isDirect = false) { IList list = new List(); @@ -96,6 +97,46 @@ namespace SiNan.Business return list; } + public IList StatisticsPopluarizeLvelROI(IList skuIdList, DateTime? startDate, DateTime? endDate, bool isDirect = false) + { + var costs = fsql.Select() + .Where(jas => skuIdList.Contains(jas.Sku)) // &&jas.Date >= startDate && jas.Date <= endDate + .WhereIf(startDate != null, jas => jas.Date >= startDate) + .WhereIf(endDate != null, jas => jas.Date <= endDate) + .GroupBy(jas => jas.Sku) + .ToList(g => new + { + Cost = g.Sum(g.Value.Cost), + Sku = g.Key + }); + + var amounts = fsql.Select() + .InnerJoin((jr, o, osku) => jr.OrderId == o.Id) + .InnerJoin((jr, o, osku) => o.Id == osku.OrderId) + .Where((jr, o, osku) => o.OrderState != Enums.OrderState.已取消 && + o.IsGift == false && + jr.CookieTime >= startDate && + jr.CookieTime <= endDate && + osku.Price > 0 && + skuIdList.Contains(jr.PopularizeSku)) + .WhereIf(isDirect, (jr, o, osku) => jr.PlaceOrderSku == jr.PopularizeSku) + .GroupBy((jr, o, osku) => jr.PopularizeSku) + .ToList(g => new PopularizeAmountBySku + { + ActualAmount = g.Sum(g.Value.Item3.ActualAmount * g.Value.Item3.ItemTotal), + Sku = g.Key + }); + IList list = new List(); + foreach (var skuId in skuIdList) + { + var cost = costs.FirstOrDefault(x => x.Sku == skuId)?.Cost ?? 0M; + var amount = amounts.FirstOrDefault(x => x.Sku == skuId)?.ActualAmount ?? 0M; + var skuroi = new ROIBySku() { Sku = skuId, Cost = cost, Amount = amount }; + list.Add(skuroi); + } + return list; + } + private GOIByShop StatisticsProductLevelGOI(long shopId, DateTime? startDate, DateTime? endDate) { var cost = fsql.Select() @@ -251,6 +292,63 @@ namespace SiNan.Business return list; } + public IList StatisticsAdSkuLvelROI(IList skuIdList, DateTime? startDate, DateTime? endDate, bool isDirect = false) + { + var costs = fsql.Select() + .Where(jas => skuIdList.Contains(jas.Sku)) // &&jas.Date >= startDate && jas.Date <= endDate + .WhereIf(startDate != null, jas => jas.Date >= startDate) + .WhereIf(endDate != null, jas => jas.Date <= endDate) + .GroupBy(jas => new { jas.Sku, jas.BusinessType, jas.CampaignId }) + .ToList(g => new + { + Cost = g.Sum(g.Value.Cost), + Sku = g.Key.Sku, + g.Key.BusinessType, + g.Key.CampaignId + }); + + var amounts = fsql.Select() + .InnerJoin((jr, o, osku) => jr.OrderId == o.Id) + .InnerJoin((jr, o, osku) => o.Id == osku.OrderId) + .Where((jr, o, osku) => o.OrderState != Enums.OrderState.已取消 && + o.IsGift == false && + jr.CookieTime >= startDate && + jr.CookieTime <= endDate && + osku.Price > 0 && + skuIdList.Contains(jr.PopularizeSku)) + .WhereIf(isDirect, (jr, o, osku) => jr.PlaceOrderSku == jr.PopularizeSku) + .GroupBy((jr, o, osku) => new { jr.PopularizeSku, jr.BusinessType, jr.CampaignId }) + .ToList(g => new PopularizeAmountBySku + { + ActualAmount = g.Sum(g.Value.Item3.ActualAmount * g.Value.Item3.ItemTotal), + Sku = g.Key.PopularizeSku, + BusinessType = g.Key.BusinessType, + CampaignId = g.Key.CampaignId + }); + + IList list = new List(); + foreach (var skuId in skuIdList) + { + var currentCosts = costs.Where(c => c.Sku == skuId).ToList(); + foreach (var cost in currentCosts) + { + var amount = amounts.FirstOrDefault(x => x.Sku == skuId && + x.BusinessType == cost.BusinessType && + x.CampaignId == cost.CampaignId); + var adskuroi = new ROIByAdSku() + { + Sku = skuId, + Cost = cost.Cost, + Amount = amount?.ActualAmount ?? 0M, + BusinessType = cost.BusinessType.Value, + CampaignId = cost.CampaignId.Value, + }; + list.Add(adskuroi); + } + } + return list; + } + public IList CalculationAdSkuProductLevelGOI(IList skuIdList, DateTime startDate, DateTime endDate) { var costs = fsql.Select() @@ -266,7 +364,7 @@ namespace SiNan.Business var profits = fsql.Select() .InnerJoin((ocd, o) => ocd.OrderId == o.Id) .Where((ocd, o) => skuIdList.Contains(ocd.SkuId) && - ocd.IsEnabled==true && + ocd.IsEnabled == true && o.StartTime >= startDate && o.StartTime <= endDate && o.OrderState != Enums.OrderState.已取消 && diff --git a/SiNan.Model/Core/ROI/ROIByAdSku.cs b/SiNan.Model/Core/ROI/ROIByAdSku.cs new file mode 100644 index 0000000..833ab64 --- /dev/null +++ b/SiNan.Model/Core/ROI/ROIByAdSku.cs @@ -0,0 +1,9 @@ +namespace SiNan.Model.Core.ROI +{ + public class ROIByAdSku : ROIBySku + { + public int BusinessType { get; set; } + + public long CampaignId { get; set; } + } +} diff --git a/SiNan.Model/Core/ROI/ROIBySku.cs b/SiNan.Model/Core/ROI/ROIBySku.cs new file mode 100644 index 0000000..56c5350 --- /dev/null +++ b/SiNan.Model/Core/ROI/ROIBySku.cs @@ -0,0 +1,7 @@ +namespace SiNan.Model.Core.ROI +{ + public class ROIBySku : ROICore + { + public string Sku { get; set; } + } +} diff --git a/SiNan.Model/Core/ROI/ROICore.cs b/SiNan.Model/Core/ROI/ROICore.cs new file mode 100644 index 0000000..b771fef --- /dev/null +++ b/SiNan.Model/Core/ROI/ROICore.cs @@ -0,0 +1,26 @@ +namespace SiNan.Model.Core +{ + public class ROICore + { + /// + /// 花费 + /// + public decimal Cost { get; set; } + + /// + /// 成交额 + /// + public decimal Amount { get; set; } + + /// + /// ROI + /// + public decimal ROI + { + get + { + return Cost == 0M ? 0M : Math.Round(Amount / Cost, 2); + } + } + } +} diff --git a/SiNan.Model/Db/Aggregation/AggregationJDPopularizeAdSkuDaily.cs b/SiNan.Model/Db/Aggregation/AggregationJDPopularizeAdSkuDaily.cs index 78b0bef..47cd701 100644 --- a/SiNan.Model/Db/Aggregation/AggregationJDPopularizeAdSkuDaily.cs +++ b/SiNan.Model/Db/Aggregation/AggregationJDPopularizeAdSkuDaily.cs @@ -87,6 +87,24 @@ namespace SiNan.Model.Db [Column(DbType = "int")] public int? Clicks { get; set; } = 0; + + /// + /// 推广维度ROI + /// + [Column(DbType = "decimal(18,2)")] + public decimal? PopularizeLevelROI { get; set; } = 0.00M; + + /// + /// 直接推广营业额(SKU实收) + /// + [Column(DbType = "decimal(18,2)")] + public decimal? DirectPopularizeAmount { get; set; } = 0.00M; + + /// + /// 直接推广维度ROI + /// + [Column(DbType = "decimal(18,2)")] + public decimal? DirectPopularizeLevelROI { get; set; } = 0.00M; } } diff --git a/SiNan.Model/Db/Aggregation/AggregationJDPopularizeSku.cs b/SiNan.Model/Db/Aggregation/AggregationJDPopularizeSku.cs index 5c363ca..50ecc5b 100644 --- a/SiNan.Model/Db/Aggregation/AggregationJDPopularizeSku.cs +++ b/SiNan.Model/Db/Aggregation/AggregationJDPopularizeSku.cs @@ -1,4 +1,5 @@ using FreeSql.DataAnnotations; +using System.Text; namespace SiNan.Model.Db { @@ -120,6 +121,12 @@ namespace SiNan.Model.Db [Column(DbType = "datetime")] public DateTime? Date { get; set; } + /// + /// 近7天推广维度ROI + /// + [Column(DbType = "decimal(18,2)")] + public decimal? Recent7dPopularizeLevelROI { get; set; } = 0.00M; + } } diff --git a/SiNan.Model/Db/Aggregation/AggregationJDPopularizeSkuDaily.cs b/SiNan.Model/Db/Aggregation/AggregationJDPopularizeSkuDaily.cs index a321cca..ea8c2d5 100644 --- a/SiNan.Model/Db/Aggregation/AggregationJDPopularizeSkuDaily.cs +++ b/SiNan.Model/Db/Aggregation/AggregationJDPopularizeSkuDaily.cs @@ -67,6 +67,29 @@ namespace SiNan.Model.Db [Column(DbType = "decimal(18,2)")] public decimal? ActualAmount { get; set; } = 0.00M; + /// + /// 推广营业额(SKU实收) + /// + [Column(DbType = "decimal(18,2)")] + public decimal? PopularizeAmount { get; set; } = 0.00M; + + /// + /// 推广维度ROI + /// + [Column(DbType = "decimal(18,2)")] + public decimal? PopularizeLevelROI { get; set; } = 0.00M; + + /// + /// 直接推广营业额(SKU实收) + /// + [Column(DbType = "decimal(18,2)")] + public decimal? DirectPopularizeAmount { get; set; } = 0.00M; + + /// + /// 直接推广维度ROI + /// + [Column(DbType = "decimal(18,2)")] + public decimal? DirectPopularizeLevelROI { get; set; } = 0.00M; } }