diff --git a/SiNan.Business/GOIBusiness.cs b/SiNan.Business/GOIBusiness.cs index a66327e..1f73a5f 100644 --- a/SiNan.Business/GOIBusiness.cs +++ b/SiNan.Business/GOIBusiness.cs @@ -337,12 +337,124 @@ namespace SiNan.Business public ListResponse QueryProductGOI(QueryProductGOIRequest request) { - return new ListResponse(); + if (request.ShopId == 0) + throw new BusinessException("缺少店铺Id"); + + if (request.PageSize > 10) + request.PageSize = 10; + + var productList = fsql.Select() + .InnerJoin((p, ap) => p.Id == ap.Id) + .Where((p, ap) => p.State == 8) + .WhereIf(!string.IsNullOrEmpty(request.SpuTitle), (p, ap) => p.Title.Contains(request.SpuTitle)) + .WhereIf(!string.IsNullOrEmpty(request.Spu), (p, ap) => p.Id == request.Spu) + .OrderByDescending((p, ap) => p.CreateTime) + .Page(request.PageIndex, request.PageSize) + .Count(out var productCount) + .ToList((p, ap) => new TempProduct() + { + Id = p.Id, + CreateTime = p.CreateTime, + Platform = p.Platform, + ProductItemNum = p.ProductItemNum, + ShopId = p.ShopId, + Stage = p.Stage, + State = p.State, + Title = p.Title, + YestodayCost = ap.YestodayCost, + YestodayProductLevelProfit = ap.YestodayProductLevelProfit, + YestodayProductLevelGOI = ap.YestodayProductLevelGOI, + YestodayPopularizeLevelProfit = ap.YestodayPopularizeLevelProfit, + YestodayPopularizeLevelGOI = ap.YestodayPopularizeLevelGOI, + Recent7dCost = ap.Recent7dCost, + Recent7dProductLevelProfit = ap.Recent7dProductLevelProfit, + Recent7dProductLevelGOI = ap.Recent7dProductLevelGOI, + Recent7dPopularizeLevelProfit = ap.Recent7dPopularizeLevelProfit, + Recent7dPopularizeLevelGOI = ap.Recent7dPopularizeLevelGOI, + Recent30dCost = ap.Recent30dCost, + Recent30dPopularizeLevelGOI = ap.Recent30dPopularizeLevelGOI, + Recent30dPopularizeLevelProfit = ap.Recent30dPopularizeLevelProfit, + Recent30dProductLevelGOI = ap.Recent30dProductLevelGOI, + Recent30dProductLevelProfit = ap.Recent30dProductLevelProfit, + Date = ap.Date, + UpdateTime = ap.UpdateTime, + MaxDeficitThreshold = p.MaxDeficitThreshold + }).Map>(); + + var productIdList = productList.Select(p => p.Id).ToList(); + var skuList = fsql.Select().Where(ps => productIdList.Contains(ps.ProductId) && ps.State == 1).ToList(); + var skuIdList = skuList.Select(s => s.Id).ToList(); + + var historyPopularizeLevelGOIList = StatisticsPopularizeLevelGOI(skuIdList, null, null); + + foreach (var product in productList) + { + var currentProductSkuIdList = skuList.Where(s => s.ProductId == product.Id).Select(s => s.Id).ToList(); + product.Logo = skuList.FirstOrDefault(s => currentProductSkuIdList.Contains(s.Id))?.Logo; + var currentProductHistoryPopularizeLevelGOIList = historyPopularizeLevelGOIList.Where(x => currentProductSkuIdList.Contains(x.Sku)); + + var totalCost = currentProductHistoryPopularizeLevelGOIList.Sum(x => x.Cost); + var totalProfit = currentProductHistoryPopularizeLevelGOIList.Sum(x => x.Profit); + + product.TotalCost = totalCost; + product.TotalDeficit = totalProfit - totalCost; + } + + return new ListResponse() { ItemList = productList, Count = productCount }; } public ListResponse QueryProductSkuGOI(QueryProductSkuGOIRequest request) { - return new ListResponse(); + if (!string.IsNullOrEmpty(request.Spu)) + throw new BusinessException("缺少spu"); + + var productSkuList = fsql.Select() + .InnerJoin((ps, aps) => ps.Id == aps.Id) + .Where((ps, aps) => ps.State == 1) + .Where((ps, aps) => ps.Id == request.Spu) + .OrderByDescending((ps, aps) => ps.CreateTime) + .ToList((ps, aps) => new TempProductSku() + { + Id = ps.Id, + CreateTime = ps.CreateTime, + ShopId = ps.ShopId, + State = ps.State, + Title = ps.Title, + CategoryId = ps.CategoryId, + CategoryName = ps.CategoryName, + Logo = ps.Logo, + Platform = ps.Platform, + Price = ps.Price, + ProductId = ps.ProductId, + YestodayCost = aps.YestodayCost, + YestodayProductLevelProfit = aps.YestodayProductLevelProfit, + YestodayProductLevelGOI = aps.YestodayProductLevelGOI, + YestodayPopularizeLevelProfit = aps.YestodayPopularizeLevelProfit, + YestodayPopularizeLevelGOI = aps.YestodayPopularizeLevelGOI, + Recent7dCost = aps.Recent7dCost, + Recent7dProductLevelProfit = aps.Recent7dProductLevelProfit, + Recent7dProductLevelGOI = aps.Recent7dProductLevelGOI, + Recent7dPopularizeLevelProfit = aps.Recent7dPopularizeLevelProfit, + Recent7dPopularizeLevelGOI = aps.Recent7dPopularizeLevelGOI, + Recent30dCost = aps.Recent30dCost, + Recent30dPopularizeLevelGOI = aps.Recent30dPopularizeLevelGOI, + Recent30dPopularizeLevelProfit = aps.Recent30dPopularizeLevelProfit, + Recent30dProductLevelGOI = aps.Recent30dProductLevelGOI, + Recent30dProductLevelProfit = aps.Recent30dProductLevelProfit, + Date = aps.Date, + UpdateTime = aps.UpdateTime, + MaxDeficitThreshold = ps.MaxDeficitThreshold + }).Map>(); + + var skuIdList = productSkuList.Select(ps => ps.Id).ToList(); + var historyPopularizeLevelGOIList = StatisticsPopularizeLevelGOI(skuIdList, null, null); + foreach (var productSku in productSkuList) + { + var historyPopularizeLevelGOI = historyPopularizeLevelGOIList.FirstOrDefault(x => x.Sku == productSku.Id); + productSku.TotalCost = historyPopularizeLevelGOI?.Cost ?? 0M; + productSku.TotalDeficit = (historyPopularizeLevelGOI?.Profit ?? 0M) - (historyPopularizeLevelGOI?.Cost ?? 0M); + } + return new ListResponse() { ItemList = productSkuList, Count = productSkuList.Count() }; } public ListResponse QueryProduct360PopularizeGOI(Product360PopularizeAnalysisRequest request) diff --git a/SiNan.Model/Core/TempProduct/TempProduct.cs b/SiNan.Model/Core/TempProduct/TempProduct.cs new file mode 100644 index 0000000..a7c0212 --- /dev/null +++ b/SiNan.Model/Core/TempProduct/TempProduct.cs @@ -0,0 +1,108 @@ +using SiNan.Model.Db; + +namespace SiNan.Model.Core +{ + public class TempProduct : Product + { + #region Ingore + /// + /// 近30天推广花费 + /// + + public decimal? Recent30dCost { get; set; } + + /// + /// 近30天推广维度GOI + /// + + public decimal? Recent30dPopularizeLevelGOI { get; set; } + + /// + /// 近30天推广维度毛利 + /// + + public decimal? Recent30dPopularizeLevelProfit { get; set; } + + /// + /// 近30天产品维度GOI + /// + + public decimal? Recent30dProductLevelGOI { get; set; } + + /// + /// 近30天产品维度毛利 + /// + + public decimal? Recent30dProductLevelProfit { get; set; } + + /// + /// 近7天推广花费 + /// + + public decimal? Recent7dCost { get; set; } + + /// + /// 近7天推广维度GOI + /// + + public decimal? Recent7dPopularizeLevelGOI { get; set; } + + /// + /// 近7天推广维度毛利 + /// + + public decimal? Recent7dPopularizeLevelProfit { get; set; } + + /// + /// 近7天产品维度GOI + /// + + public decimal? Recent7dProductLevelGOI { get; set; } + + /// + /// 近7天产品维度毛利 + /// + + public decimal? Recent7dProductLevelProfit { get; set; } + + + public DateTime? UpdateTime { get; set; } + + /// + /// 昨天推广花费 + /// + + public decimal? YestodayCost { get; set; } + + /// + /// 昨天推广维度GOI + /// + + public decimal? YestodayPopularizeLevelGOI { get; set; } + + /// + /// 昨天推广维度毛利 + /// + + public decimal? YestodayPopularizeLevelProfit { get; set; } + + /// + /// 昨天产品维度GOI + /// + + public decimal? YestodayProductLevelGOI { get; set; } + + /// + /// 昨天产品维度毛利 + /// + + public decimal? YestodayProductLevelProfit { get; set; } + + /// + /// 数据日期 + /// + + public DateTime? Date { get; set; } + #endregion + } +} diff --git a/SiNan.Model/Core/TempProduct/TempProductSku.cs b/SiNan.Model/Core/TempProduct/TempProductSku.cs new file mode 100644 index 0000000..cb8cada --- /dev/null +++ b/SiNan.Model/Core/TempProduct/TempProductSku.cs @@ -0,0 +1,99 @@ +using SiNan.Model.Db; + +namespace SiNan.Model.Core +{ + public class TempProductSku : ProductSku + { + /// + /// 近30天推广花费 + /// + public decimal? Recent30dCost { get; set; } + + /// + /// 近30天推广维度GOI + /// + public decimal? Recent30dPopularizeLevelGOI { get; set; } + + /// + /// 近30天推广维度毛利 + /// + public decimal? Recent30dPopularizeLevelProfit { get; set; } + + /// + /// 近30天产品维度GOI + /// + public decimal? Recent30dProductLevelGOI { get; set; } + + /// + /// 近30天产品维度毛利 + /// + public decimal? Recent30dProductLevelProfit { get; set; } + + /// + /// 近7天推广花费 + /// + public decimal? Recent7dCost { get; set; } + + /// + /// 近7天推广维度GOI + /// + + public decimal? Recent7dPopularizeLevelGOI { get; set; } + + /// + /// 近7天推广维度毛利 + /// + + public decimal? Recent7dPopularizeLevelProfit { get; set; } + + /// + /// 近7天产品维度GOI + /// + + public decimal? Recent7dProductLevelGOI { get; set; } + + /// + /// 近7天产品维度毛利 + /// + + public decimal? Recent7dProductLevelProfit { get; set; } + + + public DateTime? UpdateTime { get; set; } + + /// + /// 昨天推广花费 + /// + + public decimal? YestodayCost { get; set; } + + /// + /// 昨天推广维度GOI + /// + + public decimal? YestodayPopularizeLevelGOI { get; set; } + + /// + /// 昨天推广维度毛利 + /// + + public decimal? YestodayPopularizeLevelProfit { get; set; } + + /// + /// 昨天产品维度GOI + /// + + public decimal? YestodayProductLevelGOI { get; set; } + + /// + /// 昨天产品维度毛利 + /// + + public decimal? YestodayProductLevelProfit { get; set; } + + /// + /// 数据日期 + /// + public DateTime? Date { get; set; } + } +} diff --git a/SiNan.Model/Db/Product/Product.cs b/SiNan.Model/Db/Product/Product.cs index 0e1adf7..fe3353b 100644 --- a/SiNan.Model/Db/Product/Product.cs +++ b/SiNan.Model/Db/Product/Product.cs @@ -54,7 +54,7 @@ namespace SiNan.Model.Db /// [Column(DbType = "decimal(18,2)")] public decimal? MaxDeficitThreshold { get; set; } = 0.00M; - + #endregion } } diff --git a/SiNan.Model/Dto/Request/GOI/QueryProductSkuGOIRequest.cs b/SiNan.Model/Dto/Request/GOI/QueryProductSkuGOIRequest.cs index ccf6a80..df86995 100644 --- a/SiNan.Model/Dto/Request/GOI/QueryProductSkuGOIRequest.cs +++ b/SiNan.Model/Dto/Request/GOI/QueryProductSkuGOIRequest.cs @@ -7,7 +7,5 @@ public DateTime StartDate { get; set; } public DateTime EndDate { get; set; } - - public long? ShopId { get; set; } } } diff --git a/SiNan.Model/Dto/Response/GOI/ProductGOIResponse.cs b/SiNan.Model/Dto/Response/GOI/ProductGOIResponse.cs index ae2f508..6e32cfa 100644 --- a/SiNan.Model/Dto/Response/GOI/ProductGOIResponse.cs +++ b/SiNan.Model/Dto/Response/GOI/ProductGOIResponse.cs @@ -38,19 +38,17 @@ public decimal TotalCost { get; set; } /// - /// 累计亏损 + /// 累计亏损 (正赚负亏) /// public decimal TotalDeficit { get; set; } /// /// 最大亏损 /// - public decimal MaxDeficit { get; set; } + public decimal MaxDeficit { get { return MaxDeficitThreshold ?? 0M; } } - /// - /// SKU GOI - /// - public List ProductSkuGOIList { get; set; } + + //public List ProductSkuGOIList { get; set; } } diff --git a/SiNan.Model/MappingProfiles.cs b/SiNan.Model/MappingProfiles.cs index 8462ee7..ced72fa 100644 --- a/SiNan.Model/MappingProfiles.cs +++ b/SiNan.Model/MappingProfiles.cs @@ -1,4 +1,5 @@ using AutoMapper; +using SiNan.Model.Core; using SiNan.Model.Dto; namespace SiNan.Model @@ -9,6 +10,32 @@ namespace SiNan.Model { CreateMap(); CreateMap(); + + CreateMap().ForPath(t => t.ProductGOI_Yestoday.Cost, opt => opt.MapFrom(f => f.YestodayCost)) + .ForPath(t => t.ProductGOI_Yestoday.Profit, opt => opt.MapFrom(f => f.YestodayProductLevelProfit)) + .ForPath(t => t.PromotionGOI_Yestoday.Cost, opt => opt.MapFrom(f => f.YestodayCost)) + .ForPath(t => t.PromotionGOI_Yestoday.Profit, opt => opt.MapFrom(f => f.YestodayPopularizeLevelProfit)) + .ForPath(t => t.ProductGOI_Recent7Day.Cost, opt => opt.MapFrom(f => f.Recent7dCost)) + .ForPath(t => t.ProductGOI_Recent7Day.Profit, opt => opt.MapFrom(f => f.Recent7dProductLevelProfit)) + .ForPath(t => t.PromotionGOI_Recent7Day.Cost, opt => opt.MapFrom(f => f.Recent7dCost)) + .ForPath(t => t.PromotionGOI_Recent7Day.Profit, opt => opt.MapFrom(f => f.Recent7dPopularizeLevelProfit)) + .ForPath(t => t.ProductGOI_Recent30Day.Cost, opt => opt.MapFrom(f => f.Recent30dCost)) + .ForPath(t => t.ProductGOI_Recent30Day.Profit, opt => opt.MapFrom(f => f.Recent30dProductLevelProfit)) + .ForPath(t => t.PromotionGOI_Recent30Day.Cost, opt => opt.MapFrom(f => f.Recent30dCost)) + .ForPath(t => t.PromotionGOI_Recent30Day.Profit, opt => opt.MapFrom(f => f.Recent30dPopularizeLevelProfit)); + + CreateMap().ForPath(t => t.ProductGOI_Yestoday.Cost, opt => opt.MapFrom(f => f.YestodayCost)) + .ForPath(t => t.ProductGOI_Yestoday.Profit, opt => opt.MapFrom(f => f.YestodayProductLevelProfit)) + .ForPath(t => t.PromotionGOI_Yestoday.Cost, opt => opt.MapFrom(f => f.YestodayCost)) + .ForPath(t => t.PromotionGOI_Yestoday.Profit, opt => opt.MapFrom(f => f.YestodayPopularizeLevelProfit)) + .ForPath(t => t.ProductGOI_Recent7Day.Cost, opt => opt.MapFrom(f => f.Recent7dCost)) + .ForPath(t => t.ProductGOI_Recent7Day.Profit, opt => opt.MapFrom(f => f.Recent7dProductLevelProfit)) + .ForPath(t => t.PromotionGOI_Recent7Day.Cost, opt => opt.MapFrom(f => f.Recent7dCost)) + .ForPath(t => t.PromotionGOI_Recent7Day.Profit, opt => opt.MapFrom(f => f.Recent7dPopularizeLevelProfit)) + .ForPath(t => t.ProductGOI_Recent30Day.Cost, opt => opt.MapFrom(f => f.Recent30dCost)) + .ForPath(t => t.ProductGOI_Recent30Day.Profit, opt => opt.MapFrom(f => f.Recent30dProductLevelProfit)) + .ForPath(t => t.PromotionGOI_Recent30Day.Cost, opt => opt.MapFrom(f => f.Recent30dCost)) + .ForPath(t => t.PromotionGOI_Recent30Day.Profit, opt => opt.MapFrom(f => f.Recent30dPopularizeLevelProfit)); } } }