123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- 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 计算服务费
- /// <summary>
- /// 获取服务费以及到手价
- /// </summary>
- /// <param name="catId">类目id</param>
- /// <param name="salePrices">多个销售价</param>
- /// <param name="saleType">1,寄售,2挂售</param>
- /// <returns></returns>
- /// <exception cref="LogicalException"></exception>
- public static async Task<Dictionary<int, FeeInfo>> GetSalePriceByCatId(this DbRESTFulRepository repository,
- int serviceFeeTempId, List<int> salePrices, bool careNetAmount = true) {
- if (serviceFeeTempId == 0)
- throw new LogicalException("请输入正确的服务费模板id");
- List<MallServiceFee> fees = new List<MallServiceFee>();
- var feeRange = await repository.QueryAsync<MallServiceFeeRange>(@"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<int, FeeInfo>();
- 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<MallServiceFee>(), //服务费详情列表
- 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;
- }
- /// <summary>
- /// 计算服务费
- /// </summary>
- /// <param name="feeRange"></param>
- /// <param name="salePrice">单位是分</param>
- /// <returns></returns>
- private static NetServiceFee CalNetFee(IEnumerable<MallServiceFeeRange> feeRange, int salePrice) {
- List<MallServiceFee> fees = new List<MallServiceFee>();
- //到手金额
- 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 欧拉币抵扣计算
- /// <summary>
- /// 计算价值币抵扣金额
- /// </summary>
- /// <param name="planId">方案id</param>
- /// <param name="salePrice">售价</param>
- /// <returns></returns>
- public static async Task<int> CalPointsDeduct(this DbRESTFulRepository repository, int planId, int salePrice) {
- if (planId <= 0) return 0;
- // 商品价值币抵扣方案
- var pointsPlans = await repository.QueryAsync<dynamic>($@"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<int> CalDepositFee(this DbRESTFulRepository repository,
- int pickDepositId, int salePrice) {
- if (pickDepositId <= 0) return 0;
- // 商品价值币抵扣方案
- var temp = await repository.QueryAsync<dynamic>(
- $@"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 计算仓储费
- //计算取回费用 单位分
- /// <summary>
- /// 当商品上架时,要计算lastStorageTime,通过判断saleOrderCloseAt是否有值,
- /// 如果有值,将payAt-shelveAt的天数作为lastStorageTime的值。
- /// 并且要看saleOrderCloseAt和重新上架时间是否同一天。
- /// 如是,则lastStorageTime的值不向上取整,如果不是则向上取整。
- /// </summary>
- /// <param name="order"></param>
- /// <returns></returns>
- 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<MallServiceFee> fees { get; set; }
- public bool isBelowMiniPrice { get; set; }
- public string belowMiniPriceDesc { get; set; }
- }
- public class UEPickDepositRange {
- /// <summary>
- /// 主键ID
- /// </summary>
- /// <remarks>不可为空,是主键</remarks>
- public int DepositRangeId { get; set; }
- /// <summary>
- /// 方案id
- /// </summary>
- /// <remarks>不可为空</remarks>
- public int PickDepositId { get; set; }
- /// <summary>
- /// 收费方式(1,售价百分比,2,售价区间定额)
- /// </summary>
- /// <remarks>不可为空</remarks>
- public byte ChargeType { get; set; }
- /// <summary>
- /// 下区间价格(单位分)
- /// </summary>
- public int StartRange { get; set; }
- /// <summary>
- /// 上区间价格(单位分)-1表示无限制
- /// </summary>
- public int EndRange { get; set; }
- /// <summary>
- /// 保证金(单位分)
- /// </summary>
- public int DepositFee { get; set; }
- /// <summary>
- /// 保证金比率(万分比)
- /// </summary>
- public decimal DepositRate { get; set; }
- /// <summary>
- /// 最低保证金(单位分)
- /// </summary>
- public int MinDepositFee { get; set; }
- /// <summary>
- /// 最高保证金(单位分)-1表示无限制
- /// </summary>
- public int MaxDepositFee { get; set; }
- /// <summary>
- /// 创建时间-录入时间
- /// </summary>
- /// <remarks>不可为空</remarks>
- public DateTime CreateAt { get; set; }
- /// <summary>
- /// 修改时间
- /// </summary>
- public DateTime? UpdateAt { get; set; }
- }
- }
- }
|