RepositoryExtension.Temp.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. using JiaZhiQuan.Common.Models.MallGoodsModel;
  2. using JiaZhiQuan.Common.Models.VO.UE;
  3. using System.Collections.Generic;
  4. using System.Threading.Tasks;
  5. using Wicture.DbRESTFul;
  6. using Wicture.DbRESTFul.Infrastructure.Repository;
  7. using static JiaZhiQuan.Common.Models.CommonConst;
  8. using System.Linq;
  9. using System;
  10. using System.Numerics;
  11. namespace JiaZhiQuan.Common {
  12. public partial class RepositoryExtension {
  13. #region 计算服务费
  14. /// <summary>
  15. /// 获取服务费以及到手价
  16. /// </summary>
  17. /// <param name="catId">类目id</param>
  18. /// <param name="salePrices">多个销售价</param>
  19. /// <param name="saleType">1,寄售,2挂售</param>
  20. /// <returns></returns>
  21. /// <exception cref="LogicalException"></exception>
  22. public static async Task<Dictionary<int, FeeInfo>> GetSalePriceByCatId(this DbRESTFulRepository repository,
  23. int serviceFeeTempId, List<int> salePrices, bool careNetAmount = true) {
  24. if (serviceFeeTempId == 0)
  25. throw new LogicalException("请输入正确的服务费模板id");
  26. List<MallServiceFee> fees = new List<MallServiceFee>();
  27. var feeRange = await repository.QueryAsync<MallServiceFeeRange>(@"SELECT
  28. f.`name`,
  29. fr.serviceFeeId,
  30. fr.chargeType,
  31. fr.startRange,
  32. fr.endRange,
  33. fr.chargeAmount,
  34. fr.chargeRate,
  35. fr.minFee,
  36. fr.maxFee,
  37. tl.displayOrder
  38. FROM mall_servicefee_temp t
  39. INNER JOIN mall_servicefee_temp_list tl on t.id=tl.serviceFeeTempId
  40. INNER JOIN mall_service_fee f on f.id=tl.serviceFeeId
  41. INNER JOIN mall_service_fee_range fr on f.id=fr.serviceFeeId
  42. WHERE t.id=@serviceFeeTempId AND t.state=1
  43. ORDER BY fr.startRange", new { serviceFeeTempId });
  44. var result = new Dictionary<int, FeeInfo>();
  45. salePrices.ForEach(p => {
  46. var netFee = CalNetFee(feeRange, p);
  47. var rst = new FeeInfo {
  48. totalServicePrice = (int)(netFee.totalServiceFee * UNIT),
  49. totalServiceFee = "-¥" + netFee.totalServiceFee.ToString("0.##"),
  50. netAmount = (int)(netFee.netAmount * UNIT),
  51. netAmountStr = "¥" + netFee.netAmount.ToString("0.##"), //到手金额
  52. fees = netFee.fees ?? new List<MallServiceFee>(), //服务费详情列表
  53. isBelowMiniPrice = netFee.isBelowMiniPrice,
  54. belowMiniPriceDesc = netFee.isBelowMiniPrice ? $"不足¥{UE_MIN_PRICE},请重新出价" : ""
  55. };
  56. result[p] = rst;
  57. //服务费也不能大于salePrice
  58. if (rst.totalServicePrice >= p || rst.netAmount <= 0) {
  59. if (!careNetAmount) {
  60. //rst.totalServicePrice = p;
  61. rst.netAmount = 0;
  62. rst.netAmountStr = "¥" + rst.netAmount.ToString("0.##");
  63. rst.belowMiniPriceDesc = $"¥0,请重新出价";
  64. return;
  65. }
  66. throw new Exception("商品定价存在问题,服务价过高或到手价为0");
  67. }
  68. });
  69. return result;
  70. }
  71. /// <summary>
  72. /// 计算服务费
  73. /// </summary>
  74. /// <param name="feeRange"></param>
  75. /// <param name="salePrice">单位是分</param>
  76. /// <returns></returns>
  77. private static NetServiceFee CalNetFee(IEnumerable<MallServiceFeeRange> feeRange, int salePrice) {
  78. List<MallServiceFee> fees = new List<MallServiceFee>();
  79. //到手金额
  80. int netAmount = salePrice;
  81. int totalServiceFee = 0;
  82. var feeDic = feeRange.GroupBy(f => f.serviceFeeId).ToDictionary(g => g.Key, g => g.ToList());
  83. foreach (var item in feeDic) {
  84. int money = 0;
  85. string name = string.Empty;
  86. foreach (var fee in item.Value) {
  87. //,1,比例,2,定额
  88. switch (fee.chargeType) {
  89. case 1:
  90. long lmoney = (long)salePrice * fee.chargeRate;
  91. int deduction = (int)(lmoney / 10000);
  92. name = fee.name + $"({CommonUtils.DivideAndRound(fee.chargeRate, UNIT):0.##}%";
  93. if (fee.minFee.HasValue && deduction < fee.minFee.Value) {
  94. deduction = fee.minFee.Value;
  95. name += $",最低¥{CommonUtils.DivideAndRound(deduction, UNIT):0.##}";
  96. }
  97. if (fee.maxFee.HasValue && deduction > fee.maxFee.Value) {
  98. deduction = fee.maxFee.Value;
  99. name += $",最高¥{CommonUtils.DivideAndRound(deduction, UNIT):0.##}";
  100. }
  101. money = deduction;
  102. name += ")";
  103. break;
  104. case 2:
  105. money = fee.chargeAmount;
  106. name = fee.name + $"(¥{CommonUtils.DivideAndRound(money, UNIT):0.##})";
  107. break;
  108. }
  109. fees.Add(new MallServiceFee {
  110. name = name,
  111. fee = "-¥" + CommonUtils.DivideAndRound(money, UNIT).ToString("0.##"),
  112. displayOrder = fee.displayOrder,
  113. });
  114. netAmount -= money;
  115. totalServiceFee += money;
  116. }
  117. }
  118. fees = fees.OrderByDescending(f => f.displayOrder).ToList();
  119. return new NetServiceFee {
  120. fees = fees,
  121. isBelowMiniPrice = netAmount < UE_MIN_PRICE * UNIT,
  122. netAmount = CommonUtils.DivideAndRound(netAmount, UNIT),
  123. totalServiceFee = CommonUtils.DivideAndRound(totalServiceFee, UNIT)
  124. };
  125. }
  126. #endregion
  127. #region 欧拉币抵扣计算
  128. /// <summary>
  129. /// 计算价值币抵扣金额
  130. /// </summary>
  131. /// <param name="planId">方案id</param>
  132. /// <param name="salePrice">售价</param>
  133. /// <returns></returns>
  134. public static async Task<int> CalPointsDeduct(this DbRESTFulRepository repository, int planId, int salePrice) {
  135. if (planId <= 0) return 0;
  136. // 商品价值币抵扣方案
  137. var pointsPlans = await repository.QueryAsync<dynamic>($@"SELECT
  138. planRangeId,planId,chargeType,startPrice,deductionFee,
  139. deductionRate,minDeductionFee,maxDeductionFee
  140. FROM mall_points_plan_range WHERE planId = @planId", new { planId });
  141. if (pointsPlans == null || pointsPlans.Count() == 0) return 0;
  142. //配置要保证每个方案只有一种chargeType。
  143. int rst = 0;
  144. var pointsPlan = pointsPlans.First();
  145. switch ((int)pointsPlan.chargeType) {
  146. case 1://比率
  147. rst = (int)(salePrice * pointsPlan.deductionRate / 10000d);
  148. // 限制最小抵扣金额
  149. if (rst < pointsPlan.minDeductionFee) {
  150. rst = pointsPlan.minDeductionFee;
  151. }
  152. // 限制最大抵扣金额
  153. if (rst > pointsPlan.maxDeductionFee && pointsPlan.maxDeductionFee > 0) {
  154. rst = pointsPlan.maxDeductionFee;
  155. }
  156. break;
  157. case 2://满减
  158. if (salePrice >= pointsPlan.startPrice) {
  159. rst = pointsPlan.deductionFee;
  160. }
  161. break;
  162. }
  163. //此时抵扣价格应该算多少?是为0还是为salePrice
  164. rst = rst >= salePrice ? salePrice : rst;
  165. return rst;
  166. }
  167. #endregion
  168. #region 计算保证金
  169. public static async Task<int> CalDepositFee(this DbRESTFulRepository repository,
  170. int pickDepositId, int salePrice) {
  171. if (pickDepositId <= 0) return 0;
  172. // 商品价值币抵扣方案
  173. var temp = await repository.QueryAsync<dynamic>(
  174. $@"SELECT depositRangeId,pickDepositId,chargeType,startRange,
  175. endRange,depositFee, depositRate,mindepositFee,maxdepositFee
  176. FROM ue_pick_deposit_range WHERE pickDepositId = @pickDepositId",
  177. new { pickDepositId });
  178. if (temp == null || temp.Count() == 0) return 0;
  179. //配置要保证每个方案只有一种chargeType。
  180. int rst = 0;
  181. var plan = temp.First();
  182. if (1 == (int)plan.chargeType) {
  183. rst = (int)(salePrice * plan.depositRate / 10000d);
  184. // 限制最小抵扣金额
  185. if (rst < plan.mindepositFee) {
  186. rst = plan.mindepositFee;
  187. }
  188. // 限制最大抵扣金额
  189. if (rst > plan.maxdepositFee && plan.maxdepositFee > 0) {
  190. rst = plan.maxdepositFee;
  191. }
  192. } else if (2 == (int)plan.chargeType) {
  193. temp.ForEach(p => {
  194. if (p.endRange == null || (int)p.endRange == -1) {
  195. p.endRange = (object)int.MaxValue;
  196. }
  197. });
  198. var deposit = temp.FirstOrDefault(p => (int)p.startRange <= salePrice && (int)p.endRange >= salePrice);
  199. rst = deposit?.depositFee ?? 0;
  200. }
  201. //此时抵扣价格应该算多少?是为0还是为salePrice
  202. rst = rst >= salePrice ? salePrice : rst;
  203. return rst;
  204. }
  205. #endregion
  206. #region 计算仓储费
  207. //计算取回费用 单位分
  208. /// <summary>
  209. /// 当商品上架时,要计算lastStorageTime,通过判断saleOrderCloseAt是否有值,
  210. /// 如果有值,将payAt-shelveAt的天数作为lastStorageTime的值。
  211. /// 并且要看saleOrderCloseAt和重新上架时间是否同一天。
  212. /// 如是,则lastStorageTime的值不向上取整,如果不是则向上取整。
  213. /// </summary>
  214. /// <param name="order"></param>
  215. /// <returns></returns>
  216. public static (int getbackFee, int getbackDays) CalGetBackFee(
  217. this DbRESTFulRepository repository, UEPostOrder order) {
  218. //计算天数
  219. if (order.shelveAt == null) return (0, 0);
  220. var dDays = 0d;
  221. if (order.getbackAt == null && order.payAt == null) {
  222. dDays = (DateTime.Now - order.shelveAt).Value.TotalDays + (double)order.lastStorageTime;
  223. } else if (order.getbackAt == null && order.payAt.HasValue) {
  224. dDays = (order.payAt - order.shelveAt).Value.TotalDays + (double)order.lastStorageTime;
  225. } else if (order.getbackAt.HasValue && order.payAt == null) {
  226. dDays = (order.getbackAt - order.shelveAt).Value.TotalDays;
  227. } else {
  228. dDays = (order.getbackAt - order.saleOrderCloseAt).Value.TotalDays + (double)order.lastStorageTime;
  229. }
  230. var getbackDays = (int)Math.Ceiling(dDays);
  231. var getbackFee = getbackDays - order.upDays <= 0 ? 0 :
  232. (getbackDays - order.upDays) * order.unitStorageFee;
  233. return (getbackFee, getbackDays);
  234. }
  235. #endregion
  236. public class FeeInfo {
  237. public int totalServicePrice { get; set; }
  238. public string totalServiceFee { get; set; }
  239. public int netAmount { get; set; }
  240. public string netAmountStr { get; set; }
  241. public List<MallServiceFee> fees { get; set; }
  242. public bool isBelowMiniPrice { get; set; }
  243. public string belowMiniPriceDesc { get; set; }
  244. }
  245. public class UEPickDepositRange {
  246. /// <summary>
  247. /// 主键ID
  248. /// </summary>
  249. /// <remarks>不可为空,是主键</remarks>
  250. public int DepositRangeId { get; set; }
  251. /// <summary>
  252. /// 方案id
  253. /// </summary>
  254. /// <remarks>不可为空</remarks>
  255. public int PickDepositId { get; set; }
  256. /// <summary>
  257. /// 收费方式(1,售价百分比,2,售价区间定额)
  258. /// </summary>
  259. /// <remarks>不可为空</remarks>
  260. public byte ChargeType { get; set; }
  261. /// <summary>
  262. /// 下区间价格(单位分)
  263. /// </summary>
  264. public int StartRange { get; set; }
  265. /// <summary>
  266. /// 上区间价格(单位分)-1表示无限制
  267. /// </summary>
  268. public int EndRange { get; set; }
  269. /// <summary>
  270. /// 保证金(单位分)
  271. /// </summary>
  272. public int DepositFee { get; set; }
  273. /// <summary>
  274. /// 保证金比率(万分比)
  275. /// </summary>
  276. public decimal DepositRate { get; set; }
  277. /// <summary>
  278. /// 最低保证金(单位分)
  279. /// </summary>
  280. public int MinDepositFee { get; set; }
  281. /// <summary>
  282. /// 最高保证金(单位分)-1表示无限制
  283. /// </summary>
  284. public int MaxDepositFee { get; set; }
  285. /// <summary>
  286. /// 创建时间-录入时间
  287. /// </summary>
  288. /// <remarks>不可为空</remarks>
  289. public DateTime CreateAt { get; set; }
  290. /// <summary>
  291. /// 修改时间
  292. /// </summary>
  293. public DateTime? UpdateAt { get; set; }
  294. }
  295. }
  296. }