Order.php 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. <?php
  2. /**
  3. *
  4. * @copyright ©2020 点小铺
  5. * @author hanj
  6. * @link: https://dyuit.com
  7. * Created by VSCode
  8. */
  9. namespace app\common\model\dealer;
  10. use think\Hook;
  11. use app\common\model\BaseModel;
  12. use app\common\enum\OrderType as OrderTypeEnum;
  13. /**
  14. * 分销商订单模型
  15. * Class Apply
  16. * @package app\common\model\dealer
  17. */
  18. class Order extends BaseModel
  19. {
  20. protected $name = 'dealer_order';
  21. /**
  22. * 订单模型初始化
  23. */
  24. public static function init()
  25. {
  26. parent::init();
  27. // 监听分销商订单行为管理
  28. $static = new static;
  29. Hook::listen('DealerOrder', $static);
  30. }
  31. /**
  32. * 订单所属用户
  33. * @return \think\model\relation\BelongsTo
  34. */
  35. public function user()
  36. {
  37. return $this->belongsTo('app\common\model\User');
  38. }
  39. /**
  40. * 一级分销商用户
  41. * @return \think\model\relation\BelongsTo
  42. */
  43. public function dealerFirst()
  44. {
  45. return $this->belongsTo('User', 'first_user_id');
  46. }
  47. /**
  48. * 二级分销商用户
  49. * @return \think\model\relation\BelongsTo
  50. */
  51. public function dealerSecond()
  52. {
  53. return $this->belongsTo('User', 'second_user_id');
  54. }
  55. /**
  56. * 三级分销商用户
  57. * @return \think\model\relation\BelongsTo
  58. */
  59. public function dealerThird()
  60. {
  61. return $this->belongsTo('User', 'third_user_id');
  62. }
  63. /**
  64. * 订单类型
  65. * @param $value
  66. * @return array
  67. */
  68. public function getOrderTypeAttr($value)
  69. {
  70. $types = OrderTypeEnum::getTypeName();
  71. return ['text' => $types[$value], 'value' => $value];
  72. }
  73. /**
  74. * 订单详情
  75. * @param $where
  76. * @return Order|null
  77. * @throws \think\exception\DbException
  78. */
  79. public static function detail($where)
  80. {
  81. return static::get($where);
  82. }
  83. /**
  84. * 订单详情
  85. * @param $orderId
  86. * @param $orderType
  87. * @return Order|null
  88. * @throws \think\exception\DbException
  89. */
  90. public static function getDetailByOrderId($orderId, $orderType)
  91. {
  92. return static::detail(['order_id' => $orderId, 'order_type' => $orderType]);
  93. }
  94. /**
  95. * 发放分销订单佣金
  96. * @param array|\think\Model $order 订单详情
  97. * @param int $orderType 订单类型
  98. * @return bool|false|int
  99. * @throws \think\Exception
  100. * @throws \think\exception\DbException
  101. */
  102. public static function grantMoney($order, $orderType = OrderTypeEnum::MASTER)
  103. {
  104. // 订单是否已完成
  105. if ($order['order_status']['value'] != 30) {
  106. return false;
  107. }
  108. // 佣金结算天数
  109. $settleDays = Setting::getItem('settlement', $order['wxapp_id'])['settle_days'];
  110. // 判断该订单是否满足结算时间 (订单完成时间 + 佣金结算时间) ≤ 当前时间
  111. $deadlineTime = $order['receipt_time'] + ((int)$settleDays * 86400);
  112. if ($settleDays > 0 && $deadlineTime > time()) {
  113. return false;
  114. }
  115. // 分销订单详情
  116. $model = self::getDetailByOrderId($order['order_id'], $orderType);
  117. if (!$model || $model['is_settled'] == 1) {
  118. return false;
  119. }
  120. // 重新计算分销佣金
  121. $capital = $model->getCapitalByOrder($order);
  122. // 发放一级分销商佣金
  123. $model['first_user_id'] > 0 && User::grantMoney($model['first_user_id'], $capital['first_money']);
  124. // 发放二级分销商佣金
  125. $model['second_user_id'] > 0 && User::grantMoney($model['second_user_id'], $capital['second_money']);
  126. // 发放三级分销商佣金
  127. $model['third_user_id'] > 0 && User::grantMoney($model['third_user_id'], $capital['third_money']);
  128. // 更新分销订单记录
  129. return $model->save([
  130. 'order_price' => $capital['orderPrice'],
  131. 'first_money' => $capital['first_money'],
  132. 'second_money' => $capital['second_money'],
  133. 'third_money' => $capital['third_money'],
  134. 'is_settled' => 1,
  135. 'settle_time' => time()
  136. ]);
  137. }
  138. /**
  139. * 计算订单分销佣金
  140. * @param $order
  141. * @return array
  142. */
  143. protected function getCapitalByOrder($order)
  144. {
  145. // 分销佣金设置
  146. $setting = Setting::getItem('commission', $order['wxapp_id']);
  147. // 分销层级
  148. $level = Setting::getItem('basic', $order['wxapp_id'])['level'];
  149. // 分销订单佣金数据
  150. $capital = [
  151. // 订单总金额(不含运费)
  152. 'orderPrice' => bcsub($order['pay_price'], $order['express_price'], 2),
  153. // 一级分销佣金
  154. 'first_money' => 0.00,
  155. // 二级分销佣金
  156. 'second_money' => 0.00,
  157. // 三级分销佣金
  158. 'third_money' => 0.00
  159. ];
  160. // 计算分销佣金
  161. foreach ($order['goods'] as $goods) {
  162. // 判断商品存在售后退款则不计算佣金
  163. if ($this->checkGoodsRefund($goods)) {
  164. continue;
  165. }
  166. // 商品实付款金额
  167. $goodsPrice = min($capital['orderPrice'], $goods['total_pay_price']);
  168. // 计算商品实际佣金
  169. $goodsCapital = $this->calculateGoodsCapital($setting, $goods, $goodsPrice);
  170. // 累积分销佣金
  171. $level >= 1 && $capital['first_money'] += $goodsCapital['first_money'];
  172. $level >= 2 && $capital['second_money'] += $goodsCapital['second_money'];
  173. $level == 3 && $capital['third_money'] += $goodsCapital['third_money'];
  174. }
  175. return $capital;
  176. }
  177. /**
  178. * 计算商品实际佣金
  179. * @param $setting
  180. * @param $goods
  181. * @param $goodsPrice
  182. * @return array
  183. */
  184. private function calculateGoodsCapital($setting, $goods, $goodsPrice)
  185. {
  186. // 判断是否开启商品单独分销
  187. if ($goods['is_ind_dealer'] == false) {
  188. // 全局分销比例
  189. return [
  190. 'first_money' => $goodsPrice * ($setting['first_money'] * 0.01),
  191. 'second_money' => $goodsPrice * ($setting['second_money'] * 0.01),
  192. 'third_money' => $goodsPrice * ($setting['third_money'] * 0.01)
  193. ];
  194. }
  195. // 商品单独分销
  196. if ($goods['dealer_money_type'] == 10) {
  197. // 分销佣金类型:百分比
  198. return [
  199. 'first_money' => $goodsPrice * ($goods['first_money'] * 0.01),
  200. 'second_money' => $goodsPrice * ($goods['second_money'] * 0.01),
  201. 'third_money' => $goodsPrice * ($goods['third_money'] * 0.01)
  202. ];
  203. } else {
  204. return [
  205. 'first_money' => $goods['total_num'] * $goods['first_money'],
  206. 'second_money' => $goods['total_num'] * $goods['second_money'],
  207. 'third_money' => $goods['total_num'] * $goods['third_money']
  208. ];
  209. }
  210. }
  211. /**
  212. * 验证商品是否存在售后
  213. * @param $goods
  214. * @return bool
  215. */
  216. private function checkGoodsRefund($goods)
  217. {
  218. return !empty($goods['refund'])
  219. && $goods['refund']['type']['value'] == 10
  220. && $goods['refund']['is_agree']['value'] != 20;
  221. }
  222. }