393 lines
17 KiB
C#
393 lines
17 KiB
C#
using MyCode.Project.Domain.Message.Response.BaoDian;
|
||
using MyCode.Project.Domain.Model;
|
||
using MyCode.Project.Domain.Repositories;
|
||
using MyCode.Project.Infrastructure.Common;
|
||
using MyCode.Project.Infrastructure.Constant;
|
||
using MyCode.Project.Infrastructure.Enumeration;
|
||
using MyCode.Project.Infrastructure.Exceptions;
|
||
using MyCode.Project.Infrastructure.Extensions;
|
||
using MyCode.Project.Repositories.Common;
|
||
using SqlSugar;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
|
||
namespace MyCode.Project.Services.BLL
|
||
{
|
||
public class SalesPlanCalBLL : CommonPlanCalBLL
|
||
{
|
||
#region 初始化
|
||
private readonly ILxmProductSalesScheduleRepository _lxmProductSalesScheduleRepository;
|
||
private readonly ILxmSheetItemRepository _lxmSheetItemRepository;
|
||
private readonly IAnsyDataProcessService _ansyDataProcessService;
|
||
private readonly IBdOrderSalesPlanSkuRepository _bdOrderSalesPlanSkuRepository;
|
||
private int OrderNum = 1;
|
||
public SalesPlanCalBLL(IRepository repository,
|
||
ILxmProductSalesScheduleRepository lxmProductSalesScheduleRepository,
|
||
ILxmSheetItemRepository lxmSheetItemRepository,
|
||
IAnsyDataProcessService ansyDataProcessService,
|
||
IBdOrderSalesPlanSkuRepository bdOrderSalesPlanSkuRepository
|
||
) :base(repository)
|
||
{
|
||
_repository = repository;
|
||
_lxmProductSalesScheduleRepository = lxmProductSalesScheduleRepository;
|
||
_lxmSheetItemRepository = lxmSheetItemRepository;
|
||
_ansyDataProcessService = ansyDataProcessService;
|
||
_bdOrderSalesPlanSkuRepository = bdOrderSalesPlanSkuRepository;
|
||
}
|
||
#endregion
|
||
|
||
#region Run(根据订单id来运算)
|
||
/// <summary>
|
||
/// 根据订单id来运算
|
||
/// </summary>
|
||
/// <param name="objSheetId"></param>
|
||
[TransactionCallHandler]
|
||
public void Run(object objSheetId)
|
||
{
|
||
//初始化
|
||
base.Init(objSheetId.ToString());
|
||
|
||
var checkResult = base.CheckPassed(PlanType.ProductSalesPlan);
|
||
|
||
if (!checkResult) { return; }
|
||
|
||
//先删掉可以保证该方法不断的被调用计算
|
||
_repository.Delete<BdOrderPlan>(p => p.OrderId == SheetId && p.PlanType == (int)PlanType.ProductSalesPlan);
|
||
|
||
//查看当月的该店员的产品销售计划tId && p.PlanType == (int)PlanType.ProductSalesPlan);
|
||
//_repository.Delete<BdOrderSalesPlanSku>(p => p.Ord
|
||
|
||
|
||
//得到该订单中的商品明细6
|
||
var sheetItems = _repository.Queryable<LxmSheetItem>().Where(p => p.SalesSheetId == SheetId).WithCache(100).ToList();
|
||
|
||
if (Sheet.Direct == 1)
|
||
{
|
||
var clerkSalesPlans = _repository
|
||
.Queryable<BdClerkProductSalesPlan, LxmProductSalesSchedule>((cPlan, pPlan) => new object[] {
|
||
JoinType.Left,cPlan.ProductId == pPlan.Id
|
||
})
|
||
.Where((cPlan, pPlan) => cPlan.Status == 1 && cPlan.VersionTime == VersionTime && cPlan.PlanTotalAmount > 0)
|
||
.WhereIF(Sheet.OrderClerkId == null, (cPlan, pPlan) => cPlan.ClerkId == null)
|
||
.WhereIF(Sheet.OrderClerkId != null, (cPlan, pPlan) => cPlan.ClerkId == Sheet.OrderClerkId)
|
||
.Select((cPlan, pPlan) => new ClerkProductSalesPlanResp { PlanId = cPlan.Id, PackageId = SqlFunc.ToInt64(cPlan.ProductId), PackageName = cPlan.Name, TotalPrice = pPlan.TotalPrice, SourcePackageId = pPlan.PackageId })
|
||
.WithCache(3600)
|
||
.ToList();
|
||
|
||
if (clerkSalesPlans == null || clerkSalesPlans.Count == 0) { return; }
|
||
|
||
clerkSalesPlans = clerkSalesPlans.OrderByDescending(p => p.TotalPrice).ToList();
|
||
|
||
var planSkus = _lxmProductSalesScheduleRepository.GetPackageProductList(clerkSalesPlans.Select(p => p.PackageId).ToList());
|
||
|
||
CalNormalOrder(clerkSalesPlans, planSkus, sheetItems);
|
||
}
|
||
else
|
||
{
|
||
CalRefundOrder(sheetItems);
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region AddPlanSku(写入计划SKU里面)
|
||
/// <summary>
|
||
/// 写入计划SKU里面
|
||
/// </summary>
|
||
private void AddPlanSku(List<ItemQtiyUnitPriceResp> listItem,long packageId,long sourcePackageId,long planId)
|
||
{
|
||
if (listItem.IsEmpty()) { return; }
|
||
|
||
var addList = new List<BdOrderSalesPlanSku>();
|
||
|
||
foreach (var item in listItem)
|
||
{
|
||
var temp = new BdOrderSalesPlanSku()
|
||
{
|
||
Id = IdHelper.GetNewId(),
|
||
Qty = item.TotalQty,
|
||
OrderId = Sheet.Id,
|
||
OrderTime = Sheet.CreateTime.Value,
|
||
PlanId = planId,
|
||
PackageId = packageId,
|
||
SkuId = item.SkuId,
|
||
UpdateTime = DateTime.Now,
|
||
UnitPrice = item.UnitPrice,
|
||
OrderNum = OrderNum,
|
||
SourceOrderId = Sheet.Id,
|
||
SourcePackageId = sourcePackageId
|
||
};
|
||
|
||
addList.Add(temp);
|
||
|
||
OrderNum = OrderNum + 1;
|
||
}
|
||
|
||
_repository.Add<BdOrderSalesPlanSku>(addList);
|
||
}
|
||
#endregion
|
||
|
||
#region CalNormalOrder(计算正常的订单)
|
||
/// <summary>
|
||
/// 计算正常的订单
|
||
/// </summary>
|
||
/// <param name="listClerkPlan"></param>
|
||
/// <param name="listPackage"></param>
|
||
/// <param name="listSheetItem"></param>
|
||
private void CalNormalOrder(List<ClerkProductSalesPlanResp> listClerkPlan,
|
||
List<PackageListResp> listPackage,
|
||
List<LxmSheetItem> listSheetItem)
|
||
{
|
||
var cal = false;
|
||
|
||
//只统计商品和服务
|
||
listSheetItem.RemoveAll(p => p.ItemType != 0 && p.ItemType != 1);
|
||
|
||
var notIncludeCaiZhuan = listClerkPlan.Where(p => p.PackageId != (int)PlanProductId.ColorProduct && p.PackageId != (int)PlanProductId.HairProduct).ToList();
|
||
|
||
//所有都符合才能凑成一个,且这个本身有数量;
|
||
foreach (var clerkPlan in notIncludeCaiZhuan)
|
||
{
|
||
var orderPlan = new BdOrderPlan()
|
||
{
|
||
Id = IdHelper.GetNewId(),
|
||
OrderId = Sheet.Id,
|
||
OrderTime = Sheet.CreateTime.Value,
|
||
PackageId = clerkPlan.PackageId,
|
||
PackageName = clerkPlan.PackageName,
|
||
PlanId = clerkPlan.PlanId,
|
||
PlanType = (int)PlanType.ProductSalesPlan,
|
||
UpdateTime = DateTime.Now,
|
||
SourcePackageId = clerkPlan.SourcePackageId,
|
||
SourceOrderId = Sheet.Id
|
||
};
|
||
|
||
//得到数量+金额,每次匹配到一个SKU就减少下数量
|
||
var matchQtyAndAmount = MatchPlanQty(listPackage, clerkPlan.PackageId, listSheetItem);
|
||
|
||
if (matchQtyAndAmount == null || matchQtyAndAmount.Qty == 0) { continue; }
|
||
|
||
orderPlan.Qty = matchQtyAndAmount.Qty;
|
||
orderPlan.Amount = matchQtyAndAmount.Amount;
|
||
|
||
orderPlan.Info = "符合[销售计划],商品或服务数需要相应减少且有跨月退款问题";
|
||
_repository.Add<BdOrderPlan>(orderPlan);
|
||
|
||
AddPlanSku(matchQtyAndAmount.Sku,clerkPlan.PackageId,clerkPlan.SourcePackageId,clerkPlan.PlanId);
|
||
|
||
cal = true;
|
||
}
|
||
|
||
var listColorAndHairClerkPlan = listClerkPlan.Where(p => (p.PackageId == (int)PlanProductId.ColorProduct || p.PackageId == (int)PlanProductId.HairProduct)).ToList();
|
||
|
||
var calOther = false;
|
||
|
||
if (listColorAndHairClerkPlan != null && listColorAndHairClerkPlan.Count > 0)
|
||
{
|
||
CalColorAndHairProduct(listColorAndHairClerkPlan, listSheetItem,out calOther);
|
||
|
||
//算完了其它类型,把数量改为0
|
||
if (calOther) { cal = true; }
|
||
}
|
||
|
||
}
|
||
#endregion
|
||
|
||
#region CalColorAndHairProduct(处理彩妆和发饰)
|
||
/// <summary>
|
||
/// 处理彩妆和发饰
|
||
/// </summary>
|
||
private void CalColorAndHairProduct(List<ClerkProductSalesPlanResp> listClerkPlan,
|
||
List<LxmSheetItem> listSheetItem,
|
||
out bool calOther)
|
||
{
|
||
calOther = false;
|
||
|
||
if (listSheetItem == null || listSheetItem.Count == 0) { return; }
|
||
if (listClerkPlan == null || listClerkPlan.Count == 0) { return; }
|
||
|
||
//彩妆和发饰,数量为0,计算金额就好;
|
||
foreach (var clerkPlan in listClerkPlan)
|
||
{
|
||
var orderPlan = new BdOrderPlan()
|
||
{
|
||
Id = IdHelper.GetNewId(),
|
||
OrderId = Sheet.Id,
|
||
OrderTime = Sheet.CreateTime.Value,
|
||
PackageId = clerkPlan.PackageId,
|
||
PackageName = clerkPlan.PackageName,
|
||
PlanId = clerkPlan.PlanId,
|
||
PlanType = (int)PlanType.ProductSalesPlan,
|
||
UpdateTime = DateTime.Now,
|
||
Qty = 0
|
||
};
|
||
|
||
//彩妆和发饰
|
||
if (clerkPlan.PackageId == (int)PlanProductId.ColorProduct || clerkPlan.PackageId == (int)PlanProductId.HairProduct)
|
||
{
|
||
var categoryId = Const.CosmeticsTopCategoryId;
|
||
|
||
if (clerkPlan.PackageId == (int)PlanProductId.HairProduct) { categoryId = Const.HairOrnamentsTopCategoryId; }
|
||
|
||
var colorProducts = listSheetItem.Where(p => p.TopCategoryId == categoryId.ToLower() && p.Qty > 0 && p.InBlanceUnitPrice >0).ToList();
|
||
if (colorProducts == null || colorProducts.Count == 0) { continue; }
|
||
orderPlan.Amount = colorProducts.Sum(p => p.InBlanceUnitPrice * p.Qty);
|
||
_repository.Add<BdOrderPlan>(orderPlan);
|
||
calOther = true;
|
||
listSheetItem.RemoveAll(p => (colorProducts.Select(it => it.Id)).Contains(p.Id));
|
||
}
|
||
}
|
||
|
||
}
|
||
#endregion
|
||
|
||
#region MatchPlanQty(匹配计划中的套餐多少套)
|
||
/// <summary>
|
||
/// 匹配计划中的套餐可以多少套
|
||
/// </summary>
|
||
/// <param name="orderSkuId"></param>
|
||
/// <param name="listPlanSkuId"></param>
|
||
/// <returns></returns>
|
||
private MatchPlanQtyResp MatchPlanQty(List<PackageListResp> listPackage,
|
||
long packageId,
|
||
List<LxmSheetItem> listSheetItem)
|
||
{
|
||
//匹配到的计划配置里面的sku
|
||
var matchPlanSkus = listPackage.Where(p => p.Id == packageId).ToList();
|
||
|
||
if (matchPlanSkus.IsEmpty()) { return null; }
|
||
|
||
foreach (var planSku in matchPlanSkus)
|
||
{
|
||
//先判断是否套餐的所有商品在里面都有
|
||
if (!listSheetItem.Exists(p => p.ItemId.ToLower() == planSku.ProductOrServiceId.ToLower() && p.Qty >= planSku.Qty))
|
||
{
|
||
return null;
|
||
}
|
||
}
|
||
|
||
//默认只能一套
|
||
var listMatchQty = new List<int>();
|
||
|
||
//符合套餐,看看可以得到多少套
|
||
for (int i = 0; i < matchPlanSkus.Count; i++)
|
||
{
|
||
var matchProduct = listSheetItem.Find(p => p.ItemId.ToLower() == matchPlanSkus[i].ProductOrServiceId.ToLower());
|
||
|
||
// 上面已经匹配,这里不可能为null,只关心可以得到多少
|
||
var tempQty = matchProduct.Qty / matchPlanSkus[i].Qty;
|
||
listMatchQty.Add(tempQty);
|
||
}
|
||
|
||
var matchQty = listMatchQty.Min(p => p);
|
||
var amount = 0m;
|
||
|
||
var listMatchItem = new List<ItemQtiyUnitPriceResp>();
|
||
|
||
//按这个数量移除
|
||
for (int i = 0; i < matchPlanSkus.Count; i++)
|
||
{
|
||
var matchProduct = listSheetItem.Find(p => p.ItemId.ToLower() == matchPlanSkus[i].ProductOrServiceId.ToLower());
|
||
amount = amount + Math.Round(matchProduct.InBlanceUnitPrice * matchQty,2,MidpointRounding.AwayFromZero);
|
||
|
||
var matchItem = new ItemQtiyUnitPriceResp()
|
||
{
|
||
TotalQty = matchPlanSkus[i].Qty * matchQty,
|
||
SkuId = matchProduct.ItemId,
|
||
UnitPrice = matchProduct.InBlanceUnitPrice
|
||
};
|
||
|
||
listMatchItem.Add(matchItem);
|
||
|
||
//订单明细这里
|
||
matchProduct.Qty = matchProduct.Qty - matchQty;
|
||
}
|
||
|
||
return new MatchPlanQtyResp { Qty = matchQty,Amount = amount, Sku = listMatchItem };
|
||
|
||
}
|
||
#endregion
|
||
|
||
#region CalRefundOrder(如果是退款单)
|
||
/// <summary>
|
||
/// 如果是退款单
|
||
/// </summary>
|
||
private void CalRefundOrder(List<LxmSheetItem> listSheetItem)
|
||
{
|
||
|
||
//这个月如果产生了或者上个月产生了,则
|
||
if (Sheet.SourceOrderId == null)
|
||
{
|
||
LogHelper.Info($"[销售运算]退款单={Sheet.Id}找不到原始订单");
|
||
return;
|
||
}
|
||
|
||
var sourceOrderId = Sheet.SourceOrderId;
|
||
|
||
//判断原始销售单是否上个月
|
||
var sourceOrder = GetSourceSimpleOrder(Sheet.SourceOrderId);
|
||
if (sourceOrder.OrderPreorderId != null) { sourceOrderId = sourceOrder.OrderPreorderId; }
|
||
|
||
//订单上个月开始时间,因为销售计划只需要计算从上个月开始就行
|
||
var sheetOrderLastMonthFirstDay = Sheet.CreateTime.Value.AddMonths(-1).GetFirstDayOfMonth();
|
||
if (sourceOrder.CreateTime < sheetOrderLastMonthFirstDay) { return; }
|
||
|
||
//如果不是全退,则不用处理
|
||
var sourceQty = _repository.Queryable<LxmSheetItem>().Where(p => p.SalesSheetId == sourceOrderId).Select(p => SqlFunc.AggregateSum(p.Qty)).First();
|
||
|
||
var refundQty = _lxmSheetItemRepository.GetRefundQty(sourceOrderId, sheetOrderLastMonthFirstDay, Sheet.CreateTime.Value.AddSeconds(1));
|
||
|
||
if (sourceQty != refundQty) { return; }
|
||
|
||
var clerkSalesPlans = _repository
|
||
.Queryable<BdClerkProductSalesPlan, LxmProductSalesSchedule>((cPlan, pPlan) => new object[] {
|
||
JoinType.Left,cPlan.ProductId == pPlan.Id
|
||
})
|
||
.Where((cPlan, pPlan) => cPlan.Status == 1 && cPlan.VersionTime == VersionTime && cPlan.PlanTotalAmount > 0)
|
||
.WhereIF(Sheet.OrderClerkId == null, (cPlan, pPlan) => cPlan.ClerkId == null)
|
||
.WhereIF(Sheet.OrderClerkId != null, (cPlan, pPlan) => cPlan.ClerkId == sourceOrder.OrderClerkId)
|
||
.Select((cPlan, pPlan) => new ClerkProductSalesPlanResp { PlanId = cPlan.Id, PackageId = SqlFunc.ToInt64(cPlan.ProductId), PackageName = cPlan.Name, TotalPrice = pPlan.TotalPrice, SourcePackageId = pPlan.PackageId })
|
||
.WithCache(3600)
|
||
.ToList();
|
||
|
||
if (clerkSalesPlans == null || clerkSalesPlans.Count == 0) { return; }
|
||
|
||
var listClerkPlan = clerkSalesPlans.OrderByDescending(p => p.TotalPrice).ToList();
|
||
|
||
//店员的销售计划id
|
||
var clerkPackageIds = listClerkPlan.Select(p => p.SourcePackageId).Distinct().ToList();
|
||
|
||
//只能在这些店员有的计划上扣
|
||
var planSkus = _repository.Queryable<BdOrderPlan>().Where(p => p.OrderId == sourceOrderId && p.PlanType == (int)PlanType.ProductSalesPlan && (p.Qty > 0 || p.Amount > 0)).ToList();
|
||
|
||
if (planSkus == null || planSkus.Count == 0)
|
||
{
|
||
LogHelper.Info($"退款单id={Sheet.Id}当前店员在上个月和这个月没有产生对应的销售计划");
|
||
return;
|
||
}
|
||
|
||
foreach (var planSku in planSkus)
|
||
{
|
||
//当前店员如果有这个计划,则可以扣减
|
||
var clerkPlan = listClerkPlan.Find(p => p.SourcePackageId == planSku.SourcePackageId);
|
||
if (clerkPlan == null) { continue; }
|
||
|
||
planSku.Qty = -planSku.Qty;
|
||
planSku.OrderId = SheetId;
|
||
planSku.PlanId = clerkPlan.PlanId;
|
||
planSku.PackageId = clerkPlan.PackageId;
|
||
planSku.OrderTime = Sheet.CreateTime.Value;
|
||
planSku.SourceOrderId = sourceOrderId;
|
||
planSku.UpdateTime = DateTime.Now;
|
||
planSku.Amount = -planSku.Amount;
|
||
planSku.Id = IdHelper.GetNewId();
|
||
planSku.Info = "[销售计划]全额退导致的反向流水";
|
||
_repository.Add<BdOrderPlan>(planSku);
|
||
}
|
||
}
|
||
#endregion
|
||
}
|
||
}
|