RepositoryExtension.MallOrder.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. using System.Data;
  2. using System.Threading.Tasks;
  3. using System;
  4. using JiaZhiQuan.Common.Config;
  5. using Wicture.DbRESTFul;
  6. using Wicture.DbRESTFul.Infrastructure.Repository;
  7. namespace JiaZhiQuan.Common
  8. {
  9. public static partial class RepositoryExtension
  10. {
  11. /// <summary>
  12. /// C2C确认收货,不包含分账
  13. /// </summary>
  14. /// <param name="orderId">订单号</param>
  15. /// <param name="userId">买家编号,如果为0,表示系统自动确认收货</param>
  16. /// <returns>是否执行成功</returns>
  17. public static async Task<bool> MallOrderConfirmReceipt(this DbRESTFulRepository repository, ConfigFromDb config, long orderId, long userId)
  18. {
  19. var count = 0;
  20. var ratingExpireAt = DateTime.Now.AddHours(config.MallOrderRatingTimeoutHours);
  21. using (var conn = repository.ConnectionManager.GetConnection(false))
  22. {
  23. conn.Open();
  24. var trans = conn.BeginTransaction();
  25. try
  26. {
  27. count = await repository.QuerySingleOrDefaultAsync<int>(@$"update mall_order set
  28. orderState={(int)MallOrderState.交易成功},
  29. userRatingState={(int)MallOrderRatingState.待评}, sellerRatingState={(int)MallOrderRatingState.待评},
  30. userRatingExpireAt='{ratingExpireAt:yyyy-MM-dd HH:mm:ss}', sellerRatingExpireAt='{ratingExpireAt:yyyy-MM-dd HH:mm:ss}'
  31. where orderId={orderId} and orderState={(int)MallOrderState.待收货};
  32. select row_count() as count;", null, conn, trans);
  33. if (count > 0)
  34. {
  35. await repository.QueryAsync<dynamic>(
  36. $@"insert into mall_order_change_events(orderId, eventName, eventDesc, operatorId, operatorType, createAt) values (
  37. @orderId, @eventName, @eventDesc, {userId}, @operatorType, now())",
  38. new
  39. {
  40. orderId,
  41. eventName = userId > 0 ? "【交易成功】买家主动确认收货" : "【交易成功】买家超时未确认收货,系统自动确认收货",
  42. eventDesc = "",
  43. operatorType = (int)(userId > 0 ? MallOrderChangeOperatorType.买家 : MallOrderChangeOperatorType.平台)
  44. }, conn, trans);
  45. }
  46. trans.Commit();
  47. }
  48. catch
  49. {
  50. trans.Rollback();
  51. throw;
  52. }
  53. }
  54. return count > 0;
  55. }
  56. /// <summary>
  57. /// 卖家分账
  58. /// </summary>
  59. /// <param name="orderId">订单号</param>
  60. /// <param name="billId">流水编号(提前生成)</param>
  61. /// <param name="cashoutTaskId">打款任务编号(提前生成)</param>
  62. /// <returns>商家到手金额(分)</returns>
  63. public static async Task<int> MallOrderSellerSettlement(this DbRESTFulRepository repository, long orderId, long billId, long cashoutTaskId)
  64. {
  65. // 确认分账信息,卖家所得 = (订单金额-订单退款金额)— [(服务费 / 订单金额)* (订单金额-订单退款金额)]
  66. using (var conn = repository.ConnectionManager.GetConnection(false))
  67. {
  68. conn.Open();
  69. var totalAfterAmount = await repository.QuerySingleOrDefaultAsync<int?>(
  70. $"select sum(refundOrderAmount - lossAmount) as amount from mall_after_sale where orderId={orderId} and state=5",
  71. null, conn) ??
  72. 0;
  73. var orderInfo =
  74. await repository.QuerySingleOrDefaultAsync<dynamic>(
  75. $"select orderAmount, serviceAmount, sellerId from mall_order where orderId={orderId}", null, conn);
  76. var orderDetailInfo = await repository.QuerySingleOrDefaultAsync<dynamic>(
  77. $"select goodsName, goodsDesc from mall_order_detail where orderId={orderId} limit 1", null, conn);
  78. var title = string.IsNullOrEmpty(orderDetailInfo.goodsName)
  79. ? (string)orderDetailInfo.goodsDesc
  80. : (string)orderDetailInfo.goodsName;
  81. if (title.Length > 100) title = title.Substring(0, 97) + "...";
  82. var sellerId = (long)orderInfo.sellerId;
  83. var orderAmount = (int)orderInfo.orderAmount;
  84. var serviceAmount = (int)Math.Floor((orderAmount - totalAfterAmount) * ((int)orderInfo.serviceAmount * 1d /
  85. orderAmount));
  86. var sellerFinalAmount = orderAmount - totalAfterAmount - serviceAmount;
  87. // 如果最终分账金额小于0.1,则不收取服务费
  88. if (sellerFinalAmount < 10)
  89. {
  90. serviceAmount = 0;
  91. sellerFinalAmount = orderAmount - totalAfterAmount;
  92. }
  93. // 记录流水并添加卖家打款任务
  94. var trans = conn.BeginTransaction();
  95. try
  96. {
  97. // 如果存在,则忽略
  98. var existBillId = await repository.QuerySingleOrDefaultAsync<long>(
  99. $"select billId from mall_bill_record where orderId={orderId} and billType={(int)MallBillRecordBillType.分账流水}",
  100. null, conn, trans);
  101. if (existBillId == 0)
  102. {
  103. var cashoutAccount = await repository.QuerySingleOrDefaultAsync<dynamic>(
  104. $"select uName, loginName, platform from n_balance_cashout_user_platform where userId={sellerId} and platform='ALIPAY'",
  105. null, conn, trans);
  106. if (sellerFinalAmount > 0)
  107. {
  108. // 同一订单,只会生成一条分账打款记录
  109. var existId = await repository.QuerySingleOrDefaultAsync<long>(
  110. $"select id from n_balance_cashout_tasks where sourceId={orderId} and sourceType={(int)BalanceCashoutTaskSourceType.C2C订单分账打款}",
  111. null, conn, trans);
  112. if (existId == 0)
  113. {
  114. await repository.QueryAsync<dynamic>(@"insert into n_balance_cashout_tasks(
  115. id, userId, sourceId, sourceType, amount, transAmount, title, uName, platform, loginName, taxRate, feeRate, feeMinAmount, status, createAt) values (
  116. @id, @userId, @sourceId, @sourceType, @amount, @transAmount, @title, @uName, @platform, @loginName, @taxRate, @feeRate, @feeMinAmount, @status, @createAt)",
  117. new
  118. {
  119. id = cashoutTaskId,
  120. userId = sellerId,
  121. sourceId = orderId,
  122. sourceType = (int)BalanceCashoutTaskSourceType.C2C订单分账打款,
  123. amount = sellerFinalAmount,
  124. transAmount = sellerFinalAmount,
  125. title,
  126. uName = cashoutAccount?.uName ?? string.Empty,
  127. platform = cashoutAccount?.platform ?? string.Empty,
  128. loginName = cashoutAccount?.loginName ?? string.Empty,
  129. taxRate = 0,
  130. feeRate = 0,
  131. feeMinAmount = 0,
  132. status = 0,
  133. createAt = DateTime.Now
  134. }, conn, trans);
  135. }
  136. }
  137. await repository.QuerySingleOrDefaultAsync<dynamic>(@"insert into mall_bill_record(
  138. billId, orderId, userId, afterSaleId, billType, taskOrderId, realAmount, refundAmount, billPoints, pointsDeductionAmount, serviceAmount, billAmount, billState, payPlatform, platformBillNo, createAt) values (
  139. @billId, @orderId, @userId, @afterSaleId, @billType, @taskOrderId, @realAmount, @refundAmount, @billPoints, @pointsDeductionAmount, @serviceAmount, @billAmount, @billState, @payPlatform, @platformBillNo, @createAt)",
  140. new
  141. {
  142. billId,
  143. orderId,
  144. userId = sellerId,
  145. afterSaleId = 0,
  146. billType = (int)MallBillRecordBillType.分账流水,
  147. taskOrderId = cashoutTaskId.ToString(),
  148. realAmount = sellerFinalAmount,
  149. refundAmount = totalAfterAmount,
  150. billPoints = 0,
  151. pointsDeductionAmount = 0,
  152. serviceAmount,
  153. billAmount = sellerFinalAmount,
  154. billState = (int)MallBillRecordBillState.待支付,
  155. payPlatform = 1,
  156. platformBillNo = string.Empty,
  157. createAt = DateTime.Now
  158. }, conn, trans);
  159. }
  160. trans.Commit();
  161. return sellerFinalAmount;
  162. }
  163. catch
  164. {
  165. trans.Rollback();
  166. throw;
  167. }
  168. }
  169. }
  170. }
  171. }