using JiaZhiQuan.Common.Models.MallGoodsModel; using JiaZhiQuan.Common.Models.VO.UE; using System.Collections.Generic; using System.Threading.Tasks; using Wicture.DbRESTFul; using Wicture.DbRESTFul.Infrastructure.Repository; using static JiaZhiQuan.Common.Models.CommonConst; using System.Linq; using System; using System.Numerics; namespace JiaZhiQuan.Common { public partial class RepositoryExtension { #region 计算服务费 /// /// 获取服务费以及到手价 /// /// 类目id /// 多个销售价 /// 1,寄售,2挂售 /// /// public static async Task> GetSalePriceByCatId(this DbRESTFulRepository repository, int serviceFeeTempId, List salePrices, bool careNetAmount = true) { if (serviceFeeTempId == 0) throw new LogicalException("请输入正确的服务费模板id"); List fees = new List(); var feeRange = await repository.QueryAsync(@"SELECT f.`name`, fr.serviceFeeId, fr.chargeType, fr.startRange, fr.endRange, fr.chargeAmount, fr.chargeRate, fr.minFee, fr.maxFee, tl.displayOrder FROM mall_servicefee_temp t INNER JOIN mall_servicefee_temp_list tl on t.id=tl.serviceFeeTempId INNER JOIN mall_service_fee f on f.id=tl.serviceFeeId INNER JOIN mall_service_fee_range fr on f.id=fr.serviceFeeId WHERE t.id=@serviceFeeTempId AND t.state=1 ORDER BY fr.startRange", new { serviceFeeTempId }); var result = new Dictionary(); salePrices.ForEach(p => { var netFee = CalNetFee(feeRange, p); var rst = new FeeInfo { totalServicePrice = (int)(netFee.totalServiceFee * UNIT), totalServiceFee = "-¥" + netFee.totalServiceFee.ToString("0.##"), netAmount = (int)(netFee.netAmount * UNIT), netAmountStr = "¥" + netFee.netAmount.ToString("0.##"), //到手金额 fees = netFee.fees ?? new List(), //服务费详情列表 isBelowMiniPrice = netFee.isBelowMiniPrice, belowMiniPriceDesc = netFee.isBelowMiniPrice ? $"不足¥{UE_MIN_PRICE},请重新出价" : "" }; result[p] = rst; //服务费也不能大于salePrice if (rst.totalServicePrice >= p || rst.netAmount <= 0) { if (!careNetAmount) { //rst.totalServicePrice = p; rst.netAmount = 0; rst.netAmountStr = "¥" + rst.netAmount.ToString("0.##"); rst.belowMiniPriceDesc = $"¥0,请重新出价"; return; } throw new Exception("商品定价存在问题,服务价过高或到手价为0"); } }); return result; } /// /// 计算服务费 /// /// /// 单位是分 /// private static NetServiceFee CalNetFee(IEnumerable feeRange, int salePrice) { List fees = new List(); //到手金额 int netAmount = salePrice; int totalServiceFee = 0; var feeDic = feeRange.GroupBy(f => f.serviceFeeId).ToDictionary(g => g.Key, g => g.ToList()); foreach (var item in feeDic) { int money = 0; string name = string.Empty; foreach (var fee in item.Value) { //,1,比例,2,定额 switch (fee.chargeType) { case 1: long lmoney = (long)salePrice * fee.chargeRate; int deduction = (int)(lmoney / 10000); name = fee.name + $"({CommonUtils.DivideAndRound(fee.chargeRate, UNIT):0.##}%"; if (fee.minFee.HasValue && deduction < fee.minFee.Value) { deduction = fee.minFee.Value; name += $",最低¥{CommonUtils.DivideAndRound(deduction, UNIT):0.##}"; } if (fee.maxFee.HasValue && deduction > fee.maxFee.Value) { deduction = fee.maxFee.Value; name += $",最高¥{CommonUtils.DivideAndRound(deduction, UNIT):0.##}"; } money = deduction; name += ")"; break; case 2: money = fee.chargeAmount; name = fee.name + $"(¥{CommonUtils.DivideAndRound(money, UNIT):0.##})"; break; } fees.Add(new MallServiceFee { name = name, fee = "-¥" + CommonUtils.DivideAndRound(money, UNIT).ToString("0.##"), displayOrder = fee.displayOrder, }); netAmount -= money; totalServiceFee += money; } } fees = fees.OrderByDescending(f => f.displayOrder).ToList(); return new NetServiceFee { fees = fees, isBelowMiniPrice = netAmount < UE_MIN_PRICE * UNIT, netAmount = CommonUtils.DivideAndRound(netAmount, UNIT), totalServiceFee = CommonUtils.DivideAndRound(totalServiceFee, UNIT) }; } #endregion #region 欧拉币抵扣计算 /// /// 计算价值币抵扣金额 /// /// 方案id /// 售价 /// public static async Task CalPointsDeduct(this DbRESTFulRepository repository, int planId, int salePrice) { if (planId <= 0) return 0; // 商品价值币抵扣方案 var pointsPlans = await repository.QueryAsync($@"SELECT planRangeId,planId,chargeType,startPrice,deductionFee, deductionRate,minDeductionFee,maxDeductionFee FROM mall_points_plan_range WHERE planId = @planId", new { planId }); if (pointsPlans == null || pointsPlans.Count() == 0) return 0; //配置要保证每个方案只有一种chargeType。 int rst = 0; var pointsPlan = pointsPlans.First(); switch ((int)pointsPlan.chargeType) { case 1://比率 rst = (int)(salePrice * pointsPlan.deductionRate / 10000d); // 限制最小抵扣金额 if (rst < pointsPlan.minDeductionFee) { rst = pointsPlan.minDeductionFee; } // 限制最大抵扣金额 if (rst > pointsPlan.maxDeductionFee && pointsPlan.maxDeductionFee > 0) { rst = pointsPlan.maxDeductionFee; } break; case 2://满减 if (salePrice >= pointsPlan.startPrice) { rst = pointsPlan.deductionFee; } break; } //此时抵扣价格应该算多少?是为0还是为salePrice rst = rst >= salePrice ? salePrice : rst; return rst; } #endregion #region 计算保证金 public static async Task CalDepositFee(this DbRESTFulRepository repository, int pickDepositId, int salePrice) { if (pickDepositId <= 0) return 0; // 商品价值币抵扣方案 var temp = await repository.QueryAsync( $@"SELECT depositRangeId,pickDepositId,chargeType,startRange, endRange,depositFee, depositRate,mindepositFee,maxdepositFee FROM ue_pick_deposit_range WHERE pickDepositId = @pickDepositId", new { pickDepositId }); if (temp == null || temp.Count() == 0) return 0; //配置要保证每个方案只有一种chargeType。 int rst = 0; var plan = temp.First(); if (1 == (int)plan.chargeType) { rst = (int)(salePrice * plan.depositRate / 10000d); // 限制最小抵扣金额 if (rst < plan.mindepositFee) { rst = plan.mindepositFee; } // 限制最大抵扣金额 if (rst > plan.maxdepositFee && plan.maxdepositFee > 0) { rst = plan.maxdepositFee; } } else if (2 == (int)plan.chargeType) { temp.ForEach(p => { if (p.endRange == null || (int)p.endRange == -1) { p.endRange = (object)int.MaxValue; } }); var deposit = temp.FirstOrDefault(p => (int)p.startRange <= salePrice && (int)p.endRange >= salePrice); rst = deposit?.depositFee ?? 0; } //此时抵扣价格应该算多少?是为0还是为salePrice rst = rst >= salePrice ? salePrice : rst; return rst; } #endregion #region 计算仓储费 //计算取回费用 单位分 /// /// 当商品上架时,要计算lastStorageTime,通过判断saleOrderCloseAt是否有值, /// 如果有值,将payAt-shelveAt的天数作为lastStorageTime的值。 /// 并且要看saleOrderCloseAt和重新上架时间是否同一天。 /// 如是,则lastStorageTime的值不向上取整,如果不是则向上取整。 /// /// /// public static (int getbackFee, int getbackDays) CalGetBackFee( this DbRESTFulRepository repository, UEPostOrder order) { //计算天数 if (order.shelveAt == null) return (0, 0); var dDays = 0d; if (order.getbackAt == null && order.payAt == null) { dDays = (DateTime.Now - order.shelveAt).Value.TotalDays + (double)order.lastStorageTime; } else if (order.getbackAt == null && order.payAt.HasValue) { dDays = (order.payAt - order.shelveAt).Value.TotalDays + (double)order.lastStorageTime; } else if (order.getbackAt.HasValue && order.payAt == null) { dDays = (order.getbackAt - order.shelveAt).Value.TotalDays; } else { dDays = (order.getbackAt - order.saleOrderCloseAt).Value.TotalDays + (double)order.lastStorageTime; } var getbackDays = (int)Math.Ceiling(dDays); var getbackFee = getbackDays - order.upDays <= 0 ? 0 : (getbackDays - order.upDays) * order.unitStorageFee; return (getbackFee, getbackDays); } #endregion public class FeeInfo { public int totalServicePrice { get; set; } public string totalServiceFee { get; set; } public int netAmount { get; set; } public string netAmountStr { get; set; } public List fees { get; set; } public bool isBelowMiniPrice { get; set; } public string belowMiniPriceDesc { get; set; } } public class UEPickDepositRange { /// /// 主键ID /// /// 不可为空,是主键 public int DepositRangeId { get; set; } /// /// 方案id /// /// 不可为空 public int PickDepositId { get; set; } /// /// 收费方式(1,售价百分比,2,售价区间定额) /// /// 不可为空 public byte ChargeType { get; set; } /// /// 下区间价格(单位分) /// public int StartRange { get; set; } /// /// 上区间价格(单位分)-1表示无限制 /// public int EndRange { get; set; } /// /// 保证金(单位分) /// public int DepositFee { get; set; } /// /// 保证金比率(万分比) /// public decimal DepositRate { get; set; } /// /// 最低保证金(单位分) /// public int MinDepositFee { get; set; } /// /// 最高保证金(单位分)-1表示无限制 /// public int MaxDepositFee { get; set; } /// /// 创建时间-录入时间 /// /// 不可为空 public DateTime CreateAt { get; set; } /// /// 修改时间 /// public DateTime? UpdateAt { get; set; } } } }