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.
383 lines
24 KiB
383 lines
24 KiB
|
|
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 System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Yitter.IdGenerator;
|
|
|
|
namespace BBWY.Server.Business
|
|
{
|
|
public class StatisticsBusiness : BaseBusiness, IDenpendency
|
|
{
|
|
private IList<Enums.OrderState> invalidOrderStateList;
|
|
private FreeSqlMultiDBManager freeSqlMultiDBManager;
|
|
|
|
public StatisticsBusiness(IFreeSql fsql, NLogManager nLogManager, IIdGenerator idGenerator, FreeSqlMultiDBManager freeSqlMultiDBManager) : base(fsql, nLogManager, idGenerator)
|
|
{
|
|
invalidOrderStateList = new List<Enums.OrderState>() { Enums.OrderState.待付款, Enums.OrderState.已取消 };
|
|
this.freeSqlMultiDBManager = freeSqlMultiDBManager;
|
|
}
|
|
|
|
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 sdProductAmount, decimal sdCost)
|
|
{
|
|
var xxRespose = detailList.FirstOrDefault(xx => xx.Spu == spuId);
|
|
if (xxRespose == null)
|
|
{
|
|
xxRespose = new XingXiangItemResponse() { Spu = spuId, Profit = 0M };
|
|
detailList.Add(xxRespose);
|
|
}
|
|
xxRespose.Profit += profit;
|
|
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,
|
|
//SellerPreferentialAmount = o.SellerPreferentialAmount,
|
|
Profit = oc.Profit
|
|
});
|
|
|
|
if (orderList.Count() == 0)
|
|
return null;
|
|
|
|
var orderIdList = orderList.Select(o => o.Id).ToList();
|
|
//查询orderSku
|
|
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();
|
|
|
|
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, 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, 0, 0);
|
|
}
|
|
|
|
//foreach (var group in spuGroups)
|
|
//{
|
|
// var spuId = group.Key;
|
|
|
|
// var profit = 0M;
|
|
// var sdCost = 0M;
|
|
// var prodcutAmount = group.Sum(osku => osku.Price * osku.ItemTotal) ?? 0; //货款
|
|
// var skuSellerPreferentialAmount = order.SellerPreferentialAmount / skuCount * group.Count(); //该SPU分摊的商家优惠金额
|
|
// prodcutAmount -= skuSellerPreferentialAmount;
|
|
// var commissionAmount = prodcutAmount * platformCommissionRatio; //该SPU的平台扣点金额
|
|
// var freightPriceByUser = order.FreightPrice == 0 ? 0 : order.FreightPrice / skuCount * group.Count(); //该SPU分摊的用户承担运费
|
|
// var currentOrderCostDetailList = orderCostDetailList.Where(ocd => ocd.OrderId == order.Id && ocd.ProductId == spuId).ToList();
|
|
// var purchaseAmount = currentOrderCostDetailList.Count() > 0 ? currentOrderCostDetailList.Sum(ocd => ocd.TotalCost) : 0;
|
|
// var deliveryFreight = currentOrderCostDetailList.Count() > 0 ? currentOrderCostDetailList.Sum(ocd => ocd.DeliveryExpressFreight) : 0;
|
|
|
|
// if (order.StorageType != Enums.StorageType.SD)
|
|
// {
|
|
// profit = prodcutAmount + freightPriceByUser - purchaseAmount - deliveryFreight - commissionAmount;
|
|
// }
|
|
// else
|
|
// {
|
|
// var sdCommissionAmount = order.SDCommissionAmount.Value / skuCount * group.Count();
|
|
// profit = 0;
|
|
// sdCost = sdCommissionAmount + commissionAmount + order.DeliveryExpressFreight ?? 0M;
|
|
// totalSDOrderCost += sdCost;
|
|
// }
|
|
// var xxRespose = detailList.FirstOrDefault(xx => xx.Spu == spuId);
|
|
// if (xxRespose == null)
|
|
// {
|
|
// xxRespose = new XingXiangItemResponse() { Spu = spuId, Profit = 0M };
|
|
// detailList.Add(xxRespose);
|
|
// }
|
|
// xxRespose.Profit += profit;
|
|
// if (order.StorageType == Enums.StorageType.SD)
|
|
// {
|
|
// xxRespose.SDOrderCount++;
|
|
// xxRespose.SDOrderAmount += prodcutAmount;
|
|
// xxRespose.SDOrderCost += sdCost;
|
|
// }
|
|
//}
|
|
}
|
|
|
|
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)
|
|
};
|
|
|
|
}
|
|
|
|
/// <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;
|
|
}
|
|
}
|
|
}
|
|
|