Files
YunTongJackYunTask/Reportapi/MyCode.Project.Services/BaoDianBLL/SalesPlanCalBLL.cs

393 lines
17 KiB
C#
Raw Normal View History

2025-07-04 09:50:02 +08:00
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
}
}