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; }
}
}
}