步步为盈
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

405 lines
24 KiB

using BBWY.Common.Http;
using BBWY.Common.Models;
using BBWY.Server.Model;
using BBWY.Server.Model.Db;
using BBWY.Server.Model.Db.Mds;
using BBWY.Server.Model.Dto;
using Newtonsoft.Json;
using Org.BouncyCastle.Ocsp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.ComTypes;
using Yitter.IdGenerator;
namespace BBWY.Server.Business
{
public class StatisticsBusiness : BaseBusiness, IDenpendency
{
private IList<Enums.OrderState> invalidOrderStateList;
private FreeSqlMultiDBManager freeSqlMultiDBManager;
private RestApiService restApiService;
public StatisticsBusiness(IFreeSql fsql, NLogManager nLogManager, IIdGenerator idGenerator, FreeSqlMultiDBManager freeSqlMultiDBManager, RestApiService restApiService) : base(fsql, nLogManager, idGenerator)
{
invalidOrderStateList = new List<Enums.OrderState>() { Enums.OrderState., Enums.OrderState. };
this.freeSqlMultiDBManager = freeSqlMultiDBManager;
this.restApiService = restApiService;
}
public OrderAchievementResponse GetOrderAchievementStatistics(OrderAchievementRequest request)
{
request.EndTime = request.EndTime.Date.AddDays(1).AddSeconds(-1);
var response = fsql.Select<Order, OrderCost>().LeftJoin((o, oc) => o.Id == oc.OrderId)
.Where((o, oc) => o.ShopId == request.ShopId &&
o.OrderState != null &&
!invalidOrderStateList.Contains(o.OrderState.Value) && //排除待付款和取消
o.StorageType != Enums.StorageType.SD &&
o.StartTime >= request.StartTime &&
o.StartTime <= request.EndTime)
.ToAggregate((o, oc) => new OrderAchievementResponse()
{
OrderCount = o.Count(),
//Profit = oc.Sum(oc.Key.Profit),
SaleAmount = o.Sum(o.Key.OrderPayment),
DeliveryExpressFreight = oc.Sum(oc.Key.DeliveryExpressFreight),
PlatformCommissionAmount = oc.Sum(oc.Key.PlatformCommissionAmount),
PurchaseAmount = oc.Sum(oc.Key.PurchaseAmount)
});
var shopPopularizeList = fsql.Select<Shoppopularize>().Where(s => s.ShopId == request.ShopId &&
s.Date >= request.StartTime &&
s.Date <= request.EndTime).ToList();
//最后一次推广花费时间
var pularizeEndDate = shopPopularizeList.Count > 0 ? shopPopularizeList.Max(s => s.Date) : null;
var pularizeEndTime = pularizeEndDate?.AddDays(1).AddSeconds(-1);
if (pularizeEndTime != null)
{
//o.StorageType != Enums.StorageType.SD &&
response.PularizeEndDate = pularizeEndDate;
var profitList = fsql.Select<Order, OrderCost>().LeftJoin((o, oc) => o.Id == oc.OrderId)
.Where((o, oc) => o.ShopId == request.ShopId &&
o.OrderState != null &&
!invalidOrderStateList.Contains(o.OrderState.Value) && //排除待付款和取消
o.StartTime >= request.StartTime &&
o.StartTime <= pularizeEndTime)
.GroupBy((o, oc) => new
{
IsSD = o.StorageType != null && o.StorageType == Enums.StorageType.SD
})
.ToList(g => new
{
g.Key.IsSD,
Value = g.Sum(g.Value.Item2.Profit)
});
var profit = profitList.FirstOrDefault(t => !t.IsSD)?.Value ?? 0M;
var sdCost = profitList.FirstOrDefault(t => t.IsSD)?.Value ?? 0M;
response.SDCost = Math.Abs(sdCost);
response.AdvCost = shopPopularizeList.Sum(s => s.Cost) + response.SDCost;
response.Profit = profit - response.AdvCost - response.TaxCost - response.EmployeeCost;
response.ShoppopularizeList = shopPopularizeList.GroupBy(s => s.ItemName).Select(g => new Shoppopularize()
{
ShopId = request.ShopId,
Cost = g.Sum(s => s.Cost),
ItemName = g.Key
}).ToList();
}
response.ShopId = request.ShopId;
return response;
}
public IList<OrderAchievementResponse> GetOrderAchievementStatisticsList(AllShopOrderAchievementRequest request)
{
var minTime = DateTime.Parse("2022-05-01");
if (request.StartTime < minTime)
request.StartTime = minTime;
request.EndTime = request.EndTime.Date.AddDays(1).AddSeconds(-1);
List<OrderAchievementResponse> list = new List<OrderAchievementResponse>();
var shopPularizeGroups = fsql.Select<Shoppopularize>().Where(s => s.Date >= request.StartTime && s.Date <= request.EndTime)
.GroupBy(s => s.ShopId)
.ToList(g => new
{
ShopId = g.Key,
MinDate = g.Min(g.Value.Date),
MaxDate = g.Max(g.Value.Date),
Cost = g.Sum(g.Value.Cost)
});
var shopPularizeDateGroups = shopPularizeGroups.GroupBy(g => new { g.MinDate, g.MaxDate }).ToList();
foreach (var dateGroup in shopPularizeDateGroups)
{
var minDate = dateGroup.Key.MinDate;
var maxDate = dateGroup.Key.MaxDate.Value.Date.AddDays(1).AddSeconds(-1);
var shopIds = dateGroup.Select(g => g.ShopId).ToList();
var responseList = fsql.Select<Order, OrderCost>().LeftJoin((o, oc) => o.Id == oc.OrderId)
.Where((o, oc) => o.OrderState != null &&
!invalidOrderStateList.Contains(o.OrderState.Value) && //排除待付款和取消
o.StartTime >= minDate &&
o.StartTime <= maxDate &&
shopIds.Contains(o.ShopId))
.GroupBy((o, oc) => o.ShopId)
.ToList((g) => new OrderAchievementResponse()
{
ShopId = g.Key,
Profit = g.Sum(g.Value.Item2.Profit)
});
foreach (var r in responseList)
{
var shopPularize = shopPularizeGroups.FirstOrDefault(s => s.ShopId == r.ShopId);
if (shopPularize != null)
r.Profit -= shopPularize.Cost;
}
list.AddRange(responseList);
}
return list;
}
private void XingXiangCumulative(IList<XingXiangItemResponse> detailList, string spuId, bool isSD, decimal profit, decimal spuProductAmount, decimal sdProductAmount, decimal sdCost)
{
var xxRespose = detailList.FirstOrDefault(xx => xx.Spu == spuId);
if (xxRespose == null)
{
xxRespose = new XingXiangItemResponse() { Spu = spuId, Profit = 0M, ActualAmount = 0M };
detailList.Add(xxRespose);
}
xxRespose.Profit += profit;
xxRespose.ActualAmount += spuProductAmount;
if (isSD)
{
xxRespose.SDOrderCount++;
xxRespose.SDOrderAmount += sdProductAmount;
xxRespose.SDOrderCost += sdCost;
}
}
public XingXinagSearchResponse XingXiangStatistics(XingXiangSearchOrderRequest xingXiangSearchOrderRequest)
{
var mdsShop = freeSqlMultiDBManager.MDSfsql.Select<Shops>().Where(s => s.ShopId == xingXiangSearchOrderRequest.ShopId.ToString()).ToOne();
var platformCommissionRatio = mdsShop.PlatformCommissionRatio ?? 0.05M;
var beginTime = xingXiangSearchOrderRequest.SearchDate.Date;
var endTime = xingXiangSearchOrderRequest.SearchDate.Date.AddDays(1).AddSeconds(-1);
IList<XingXiangItemResponse> detailList = null;
//查询订单
var orderList = fsql.Select<Order, OrderCost>().InnerJoin((o, oc) => o.Id == oc.OrderId)
.Where((o, oc) => o.ShopId == xingXiangSearchOrderRequest.ShopId)
.Where((o, oc) => o.StartTime >= beginTime && o.StartTime <= endTime)
.Where((o, oc) => !invalidOrderStateList.Contains(o.OrderState.Value))
.OrderByDescending((o, oc) => o.StartTime)
.ToList((o, oc) => new Order()
{
Id = o.Id,
//FreightPrice = o.FreightPrice,
OrderState = o.OrderState,
OrderTotalPrice = o.OrderTotalPrice,
StartTime = o.StartTime,
StorageType = o.StorageType,
ShopId = o.ShopId,
//SDCommissionAmount = oc.SDCommissionAmount,
//DeliveryExpressFreight = oc.DeliveryExpressFreight,
//PreferentialAmount = oc.PreferentialAmount,
OrderSellerPrice = o.OrderSellerPrice,
FreightPrice = o.FreightPrice,
//SellerPreferentialAmount = o.SellerPreferentialAmount,
Profit = oc.Profit
});
if (orderList.Count() == 0)
return null;
var orderIdList = orderList.Select(o => o.Id).ToList();
var orderSkuList = fsql.Select<OrderSku>().Where(osku => osku.Price != 0 && orderIdList.Contains(osku.OrderId)).ToList();
//查询成本明细
var orderCostDetailList = fsql.Select<OrderCostDetail>().Where(ocd => orderIdList.Contains(ocd.OrderId) && ocd.IsEnabled == true).ToList();
var spuIdList = orderSkuList.Select(osku => osku.ProductId).Distinct().ToList();
List<GOIBySpu> spuGoiList = null;
GOIByShop shopGoi = null;
#region spu goi
{
var httpResult = restApiService.SendRequest("http://snapi.qiyue666.com/", "Api/GOI/QueryPopularizeLevelGOIBySpuId", new
{
SpuIdList = spuIdList,
StartTime = xingXiangSearchOrderRequest.SearchDate,
EndTime = xingXiangSearchOrderRequest.SearchDate
}, null, System.Net.Http.HttpMethod.Post);
if (httpResult.StatusCode != System.Net.HttpStatusCode.OK)
throw new BusinessException("查询spu goi失败");
var listRes = JsonConvert.DeserializeObject<ApiResponse<ListResponse<GOIBySpu>>>(httpResult.Content)?.Data;
spuGoiList = listRes.ItemList;
}
#endregion
#region shop goi
{
var httpResult = restApiService.SendRequest("http://snapi.qiyue666.com/", "Api/GOI/QueryPopularizeLevelGOIByShopId", new
{
xingXiangSearchOrderRequest.ShopId,
StartTime = xingXiangSearchOrderRequest.SearchDate,
EndTime = xingXiangSearchOrderRequest.SearchDate
}, null, System.Net.Http.HttpMethod.Post);
if (httpResult.StatusCode != System.Net.HttpStatusCode.OK)
throw new BusinessException("查询店铺 goi失败");
shopGoi = JsonConvert.DeserializeObject<ApiResponse<GOIByShop>>(httpResult.Content)?.Data;
}
#endregion
detailList = new List<XingXiangItemResponse>();
foreach (var order in orderList)
{
var currentOrderSkuList = orderSkuList.Where(osku => osku.OrderId == order.Id).ToList();
if (order.StorageType == Enums.StorageType.SD)
{
XingXiangCumulative(detailList, currentOrderSkuList[0].ProductId, true, order.Profit ?? 0M, order.OrderSellerPrice, order.OrderSellerPrice + order.FreightPrice, Math.Abs(order.Profit ?? 0M));
continue;
}
var currentOrderCostDetailList = orderCostDetailList.Where(ocd => ocd.OrderId == order.Id);
var spuGroups = currentOrderSkuList.GroupBy(osku => osku.ProductId);
var tempOrderProdcutAmount = currentOrderSkuList.Sum(osku => osku.ItemTotal * osku.Price) ?? 0M;
var tempOrderCost = currentOrderCostDetailList.Count() > 0 ? currentOrderCostDetailList.Sum(ocd => ocd.TotalCost) : 0M;
var tempOrderProfit = tempOrderProdcutAmount - tempOrderCost;
foreach (var spuGroup in spuGroups)
{
var currentSpuCostDetailList = currentOrderCostDetailList.Where(ocd => ocd.ProductId == spuGroup.Key);
var tempSpuProductAmount = spuGroup.Sum(osku => osku.Price * osku.ItemTotal) ?? 0M;
var tempSpuCost = currentSpuCostDetailList.Count() > 0 ? currentSpuCostDetailList.Sum(ocd => ocd.TotalCost) : 0M;
var tempSpuProfit = tempSpuProductAmount - tempSpuCost;
var spuProfitPercent = tempOrderProfit == 0M ? 0M : tempSpuProfit / tempOrderProfit;
var realSpuProfit = (order.Profit ?? 0M) * spuProfitPercent;
XingXiangCumulative(detailList, spuGroup.Key, false, realSpuProfit, tempSpuProductAmount, 0, 0);
}
}
var shopProductAmount = orderSkuList.Sum(osku => osku.ItemTotal * osku.Price);
foreach (var d in detailList)
{
var spuGoi = spuGoiList?.FirstOrDefault(x => x.Spu == d.Spu);
if (spuGoi != null)
{
var productAmount = orderSkuList.Where(osku => osku.ProductId == d.Spu).Sum(osku => osku.ItemTotal * osku.Price);
d.SpuYingLiRatio = Math.Round((spuGoi.Profit - spuGoi.Cost) / productAmount.Value, 2);
//d.SpuYingLiRatio = Math.Round((d.Profit - spuGoi.Cost) / productAmount.Value, 2);
}
d.ShopYingLiRatio = shopProductAmount == 0 ? 0 : Math.Round((shopGoi.Profit - shopGoi.Cost) / shopProductAmount.Value, 2);
d.ShopProfitRatio = shopProductAmount == 0 ? 0 : Math.Round(shopGoi.Profit / shopProductAmount.Value, 2);
}
var sdOrderList = orderList.Where(o => o.StorageType == Enums.StorageType.SD);
return new XingXinagSearchResponse()
{
ItemList = detailList,
TotalSDOrderAmount = detailList.Sum(xx => xx.SDOrderAmount),
TotalSDOrderCount = sdOrderList.Count(),
TotalSDOrderCost = detailList.Sum(xx => xx.SDOrderCost),
TotalProfit = detailList.Sum(xx => xx.Profit),
ShopYingLiRatio = detailList.FirstOrDefault()?.ShopYingLiRatio,
ShopProfitRatio = detailList.FirstOrDefault()?.ShopProfitRatio
};
}
/// <summary>
/// bbwy订单选项卡数量统计
/// </summary>
/// <param name="shopId"></param>
/// <param name="startDate"></param>
/// <param name="endDate"></param>
/// <returns></returns>
public OrderCountStatisticsResponse GetOrderCountStatistics(long shopId)
{
//startDate = startDate.Date;
//endDate = endDate.Date.AddDays(1).AddSeconds(-1);
var dt = DateTime.Parse("2022-05-01");
var afterDt = DateTime.Parse("2022-10-01");
var response = new OrderCountStatisticsResponse();
response.WaitPurchaseCount = fsql.Select<Order>().Where(o => o.ShopId == shopId &&
o.IsGift == false &&
o.OrderState == Enums.OrderState. && o.StartTime >= dt).Count();
response.ExceptionCount = fsql.Select<Order, OrderCost>().LeftJoin((o, oc) => o.Id == oc.OrderId)
.Where((o, oc) => o.ShopId == shopId && o.StartTime >= dt &&
o.IsGift == false &&
o.OrderState != Enums.OrderState. &&
((o.StorageType != Enums.StorageType.SD && o.StorageType != null && oc.PurchaseAmount == 0M) ||
(o.StorageType != Enums.StorageType.SD && oc.PurchaseAmount + oc.DeliveryExpressFreight > o.OrderSellerPrice + o.FreightPrice) ||
(o.StorageType == null && o.OrderState != Enums.OrderState.))).Count();
response.WaitOutStoreCount = fsql.Select<Order>().Where(o => o.ShopId == shopId && o.OrderState == Enums.OrderState. && o.StartTime >= dt &&
o.IsGift == false).Count();
response.AfterSaleOrderUnhandleCount = fsql.Select<AfterSaleOrder>().Where(aso => aso.ShopId == shopId && (aso.ProductHealth == null || aso.ProductResult == null) && aso.CreateTime >= afterDt).Count();
return response;
}
public PurchaseOrderCountStatisticsResponse GetPurchaseOrderCountStatistics(long shopId)
{
var list = fsql.Select<PurchaseOrderV2>().Where(po => po.ShopId == shopId)
.GroupBy(po => po.OrderState)
.ToList(g => new
{
Count = g.Count(),
OrderState = g.Key
});
var response = new PurchaseOrderCountStatisticsResponse()
{
WaitPayCount = list.FirstOrDefault(x => x.OrderState == Enums.PurchaseOrderState.)?.Count ?? 0,
CancelCount = list.FirstOrDefault(x => x.OrderState == Enums.PurchaseOrderState.)?.Count ?? 0,
CompletedCount = list.FirstOrDefault(x => x.OrderState == Enums.PurchaseOrderState.)?.Count ?? 0,
WaitCheckCount = list.FirstOrDefault(x => x.OrderState == Enums.PurchaseOrderState.)?.Count ?? 0,
WaitComputationCount = list.FirstOrDefault(x => x.OrderState == Enums.PurchaseOrderState.)?.Count ?? 0,
WaitPurchaseCount = list.FirstOrDefault(x => x.OrderState == Enums.PurchaseOrderState. || x.OrderState == Enums.PurchaseOrderState.)?.Count ?? 0,
WaitShippment = list.FirstOrDefault(x => x.OrderState == Enums.PurchaseOrderState. || x.OrderState == Enums.PurchaseOrderState.)?.Count ?? 0,
WaitReceiveCount = list.FirstOrDefault(x => x.OrderState == Enums.PurchaseOrderState. || x.OrderState == Enums.PurchaseOrderState.)?.Count ?? 0
};
return response;
}
/// <summary>
/// SD组个人统计
/// </summary>
/// <param name="sdOperator"></param>
/// <param name="startDate"></param>
/// <param name="endDate"></param>
/// <returns></returns>
public SDGroupPersonStatisticsResponse GetSDGroupPersonStatistics(string sdOperator, DateTime startDate, DateTime endDate)
{
endDate = endDate.Date.AddDays(1).AddSeconds(-1);
return fsql.Select<Order>().Where(o => o.StorageType == Enums.StorageType.SD &&
o.SDOperator == sdOperator &&
o.StartTime >= startDate &&
o.StartTime <= endDate).ToAggregate(g => new SDGroupPersonStatisticsResponse
{
MySDCount = g.Count(),
OrderPayment = g.Sum(g.Key.OrderPayment)
});
}
/// <summary>
/// 查询sku最近销量
/// </summary>
/// <param name="skuRecentSalesRequest"></param>
/// <returns></returns>
public IList<SkuRecentSaleResponse> GetSkuRecentSales(SkuRecentSalesRequest skuRecentSalesRequest)
{
var endTime = DateTime.Now;
var startDate = DateTime.Now.Date.AddMonths(-1);
var list = fsql.Select<OrderSku>().WhereIf(skuRecentSalesRequest.SkuIds.Count() == 1, osku => osku.SkuId == skuRecentSalesRequest.SkuIds[0])
.WhereIf(skuRecentSalesRequest.SkuIds.Count() > 1, osku => skuRecentSalesRequest.SkuIds.Contains(osku.SkuId))
.Where(osku => osku.CreateTime >= startDate && osku.CreateTime <= endTime)
.GroupBy(osku => osku.SkuId)
.ToList(g => new SkuRecentSaleResponse()
{
SkuId = g.Key,
SaleCount = g.Sum(g.Value.ItemTotal.Value)
});
return list;
}
}
}