Order.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. <?php
  2. namespace app\common\model\dealer;
  3. use think\Hook;
  4. use app\common\model\BaseModel;
  5. use app\common\enum\OrderType as OrderTypeEnum;
  6. /**
  7. * 分销商订单模型
  8. * Class Apply
  9. * @package app\common\model\dealer
  10. */
  11. class Order extends BaseModel
  12. {
  13. protected $name = 'dealer_order';
  14. /**
  15. * 订单模型初始化
  16. */
  17. public static function init()
  18. {
  19. parent::init();
  20. // 监听分销商订单行为管理
  21. $static = new static;
  22. Hook::listen('DealerOrder', $static);
  23. }
  24. /**
  25. * 订单所属用户
  26. * @return \think\model\relation\BelongsTo
  27. */
  28. public function user()
  29. {
  30. return $this->belongsTo('app\common\model\User');
  31. }
  32. /**
  33. * 一级分销商用户
  34. * @return \think\model\relation\BelongsTo
  35. */
  36. public function dealerFirst()
  37. {
  38. return $this->belongsTo('User', 'first_user_id');
  39. }
  40. /**
  41. * 二级分销商用户
  42. * @return \think\model\relation\BelongsTo
  43. */
  44. public function dealerSecond()
  45. {
  46. return $this->belongsTo('User', 'second_user_id');
  47. }
  48. /**
  49. * 三级分销商用户
  50. * @return \think\model\relation\BelongsTo
  51. */
  52. public function dealerThird()
  53. {
  54. return $this->belongsTo('User', 'third_user_id');
  55. }
  56. /**
  57. * 订单类型
  58. * @param $value
  59. * @return array
  60. */
  61. public function getOrderTypeAttr($value)
  62. {
  63. $types = OrderTypeEnum::getTypeName();
  64. return ['text' => $types[$value], 'value' => $value];
  65. }
  66. /**
  67. * 订单详情
  68. * @param $where
  69. * @return Order|null
  70. * @throws \think\exception\DbException
  71. */
  72. public static function detail($where)
  73. {
  74. return static::get($where);
  75. }
  76. /**
  77. * 订单详情
  78. * @param $orderId
  79. * @param $orderType
  80. * @return Order|null
  81. * @throws \think\exception\DbException
  82. */
  83. public static function getDetailByOrderId($orderId, $orderType)
  84. {
  85. return static::detail(['order_id' => $orderId, 'order_type' => $orderType]);
  86. }
  87. /**
  88. * 发放分销订单佣金(分销订单)
  89. * @param array|\think\Model $order 订单详情
  90. * @param int $orderType 订单类型
  91. * @return bool|false|int
  92. * @throws \think\Exception
  93. * @throws \think\exception\DbException
  94. */
  95. public static function grantMoney($order, $orderType = OrderTypeEnum::MASTER)
  96. {
  97. // 订单是否已完成
  98. if ($order['order_status']['value'] != 30) {
  99. return false;
  100. }
  101. // 佣金结算天数
  102. $settleDays = Setting::getItem('settlement', $order['wxapp_id'])['settle_days'];
  103. // 判断该订单是否满足结算时间 (订单完成时间 + 佣金结算时间) ≤ 当前时间
  104. $deadlineTime = $order['receipt_time'] + ((int)$settleDays * 86400);
  105. if ($settleDays > 0 && $deadlineTime > time()) {
  106. return false;
  107. }
  108. // 分销订单详情
  109. $model = self::getDetailByOrderId($order['order_id'], $orderType);
  110. if (!$model || $model['is_settled'] == 1) {
  111. return false;
  112. }
  113. // 重新计算分销佣金
  114. $capital = $model->getCapitalByOrder($order);
  115. // 发放一级分销商佣金
  116. $model['first_user_id'] > 0 && User::grantMoney($model['first_user_id'], $capital['first_money']);
  117. // 发放二级分销商佣金
  118. $model['second_user_id'] > 0 && User::grantMoney($model['second_user_id'], $capital['second_money']);
  119. // 发放三级分销商佣金
  120. $model['third_user_id'] > 0 && User::grantMoney($model['third_user_id'], $capital['third_money']);
  121. // 更新分销订单记录
  122. return $model->save([
  123. 'order_price' => $capital['orderPrice'],
  124. 'first_money' => $capital['first_money'],
  125. 'second_money' => $capital['second_money'],
  126. 'third_money' => $capital['third_money'],
  127. 'is_settled' => 1,
  128. 'settle_time' => time()
  129. ]);
  130. }
  131. /**
  132. * 发放分销订单佣金 (直接购买订单)
  133. * @param array|\think\Model $order 订单详情
  134. * @param int $orderType 订单类型
  135. * @return bool|false|int
  136. * @throws \think\Exception
  137. * @throws \think\exception\DbException
  138. */
  139. public static function grantOrderMoney($order, $orderType = OrderTypeEnum::MASTER)
  140. {
  141. // 订单是否已完成
  142. if ($order['order_status']['value'] != 30) {
  143. return false;
  144. }
  145. // 佣金结算天数
  146. $settleDays = Setting::getItem('settlement', $order['wxapp_id'])['settle_days'];
  147. // 判断该订单是否满足结算时间 (订单完成时间 + 佣金结算时间) ≤ 当前时间
  148. $deadlineTime = $order['receipt_time'] + ((int)$settleDays * 86400);
  149. if ($settleDays > 0 && $deadlineTime > time()) {
  150. return false;
  151. }
  152. // 分销订单详情
  153. $model = \app\common\model\Order::detail(['order_id'=>$order['order_id']]);
  154. if (!$model || $model['is_settled'] == 1) {
  155. return false;
  156. }
  157. $userInfo = User::where(['user_id'=> $order['user_id'],'wxapp_id'=>$order['wxapp_id']])
  158. ->field('user_id,referee_id')
  159. ->find();
  160. $firstId = isset($userInfo['referee_id'])? $userInfo['referee_id'] : 0;
  161. if($userInfo && $firstId>0){
  162. $firstInfo = User::where(['user_id'=> $firstId,'wxapp_id'=>$order['wxapp_id']])
  163. ->field('user_id,referee_id')
  164. ->find();
  165. $secondId = isset($firstInfo['referee_id'])? $firstInfo['referee_id'] : 0;
  166. $payMoney = isset($model['total_price'])? floatval($model['total_price']) : 0;
  167. $config = Setting::getItem('commission', $order['wxapp_id']);
  168. $awardScoreRate1 = isset($config['award_score_1'])? floatval($config['award_score_1']) : 0;
  169. $awardScoreRate2 = isset($config['award_score_2'])? floatval($config['award_score_2']) : 0;
  170. // 一级佣金
  171. $awardScore1 = floatval($payMoney * $awardScoreRate1/100);
  172. $awardScore2 = floatval($payMoney * $awardScoreRate2/100);
  173. if($firstId && $firstInfo && $awardScore1>0){
  174. User::grantMoney($firstId, $awardScore1);
  175. }
  176. //二级佣金
  177. $secondInfo = User::where(['user_id'=> $secondId,'wxapp_id'=>$order['wxapp_id']])
  178. ->field('user_id,referee_id')
  179. ->find();
  180. if($firstId && $secondInfo && $awardScore2>0){
  181. User::grantMoney($secondInfo, $awardScore2);
  182. }
  183. }
  184. // 更新订单结算数据
  185. return $model->save([
  186. 'first_money' => $awardScore1,
  187. 'second_money' => $awardScore2,
  188. 'is_settled' => 1,
  189. 'settle_time' => time()
  190. ]);
  191. }
  192. /**
  193. * 发放分销订单佣金(备份旧的结算)
  194. * @param array|\think\Model $order 订单详情
  195. * @param int $orderType 订单类型
  196. * @return bool|false|int
  197. * @throws \think\Exception
  198. * @throws \think\exception\DbException
  199. */
  200. public static function grantMoneyBack($order, $orderType = OrderTypeEnum::MASTER)
  201. {
  202. // 订单是否已完成
  203. if ($order['order_status']['value'] != 30) {
  204. return false;
  205. }
  206. // 佣金结算天数
  207. $settleDays = Setting::getItem('settlement', $order['wxapp_id'])['settle_days'];
  208. // 判断该订单是否满足结算时间 (订单完成时间 + 佣金结算时间) ≤ 当前时间
  209. $deadlineTime = $order['receipt_time'] + ((int)$settleDays * 86400);
  210. if ($settleDays > 0 && $deadlineTime > time()) {
  211. return false;
  212. }
  213. // 分销订单详情
  214. $model = self::getDetailByOrderId($order['order_id'], $orderType);
  215. if (!$model || $model['is_settled'] == 1) {
  216. return false;
  217. }
  218. // 重新计算分销佣金
  219. $capital = $model->getCapitalByOrder($order);
  220. // 发放一级分销商佣金
  221. $model['first_user_id'] > 0 && User::grantMoney($model['first_user_id'], $capital['first_money']);
  222. // 发放二级分销商佣金
  223. $model['second_user_id'] > 0 && User::grantMoney($model['second_user_id'], $capital['second_money']);
  224. // 发放三级分销商佣金
  225. $model['third_user_id'] > 0 && User::grantMoney($model['third_user_id'], $capital['third_money']);
  226. // 更新分销订单记录
  227. return $model->save([
  228. 'order_price' => $capital['orderPrice'],
  229. 'first_money' => $capital['first_money'],
  230. 'second_money' => $capital['second_money'],
  231. 'third_money' => $capital['third_money'],
  232. 'is_settled' => 1,
  233. 'settle_time' => time()
  234. ]);
  235. }
  236. /**
  237. * 计算订单分销佣金
  238. * @param $order
  239. * @return array
  240. */
  241. protected function getCapitalByOrder($order)
  242. {
  243. // 分销佣金设置
  244. $setting = Setting::getItem('commission', $order['wxapp_id']);
  245. // 分销层级
  246. $level = Setting::getItem('basic', $order['wxapp_id'])['level'];
  247. // 分销订单佣金数据
  248. $capital = [
  249. // 订单总金额(不含运费)
  250. 'orderPrice' => bcsub($order['pay_price'], $order['express_price'], 2),
  251. // 一级分销佣金
  252. 'first_money' => 0.00,
  253. // 二级分销佣金
  254. 'second_money' => 0.00,
  255. // 三级分销佣金
  256. 'third_money' => 0.00
  257. ];
  258. // 计算分销佣金
  259. foreach ($order['goods'] as $goods) {
  260. // 判断商品存在售后退款则不计算佣金
  261. if ($this->checkGoodsRefund($goods)) {
  262. continue;
  263. }
  264. // 商品实付款金额
  265. $goodsPrice = min($capital['orderPrice'], $goods['total_pay_price']);
  266. // 计算商品实际佣金
  267. $goodsCapital = $this->calculateGoodsCapital($setting, $goods, $goodsPrice);
  268. // 累积分销佣金
  269. $level >= 1 && $capital['first_money'] += $goodsCapital['first_money'];
  270. $level >= 2 && $capital['second_money'] += $goodsCapital['second_money'];
  271. $level == 3 && $capital['third_money'] += $goodsCapital['third_money'];
  272. }
  273. return $capital;
  274. }
  275. /**
  276. * 计算商品实际佣金
  277. * @param $setting
  278. * @param $goods
  279. * @param $goodsPrice
  280. * @return array
  281. */
  282. private function calculateGoodsCapital($setting, $goods, $goodsPrice)
  283. {
  284. // 判断是否开启商品单独分销
  285. if ($goods['is_ind_dealer'] == false) {
  286. // 全局分销比例
  287. return [
  288. 'first_money' => $goodsPrice * ($setting['first_money'] * 0.01),
  289. 'second_money' => $goodsPrice * ($setting['second_money'] * 0.01),
  290. 'third_money' => $goodsPrice * ($setting['third_money'] * 0.01)
  291. ];
  292. }
  293. // 商品单独分销
  294. if ($goods['dealer_money_type'] == 10) {
  295. // 分销佣金类型:百分比
  296. return [
  297. 'first_money' => $goodsPrice * ($goods['first_money'] * 0.01),
  298. 'second_money' => $goodsPrice * ($goods['second_money'] * 0.01),
  299. 'third_money' => $goodsPrice * ($goods['third_money'] * 0.01)
  300. ];
  301. } else {
  302. return [
  303. 'first_money' => $goods['total_num'] * $goods['first_money'],
  304. 'second_money' => $goods['total_num'] * $goods['second_money'],
  305. 'third_money' => $goods['total_num'] * $goods['third_money']
  306. ];
  307. }
  308. }
  309. /**
  310. * 验证商品是否存在售后
  311. * @param $goods
  312. * @return bool
  313. */
  314. private function checkGoodsRefund($goods)
  315. {
  316. return !empty($goods['refund'])
  317. && $goods['refund']['type']['value'] == 10
  318. && $goods['refund']['is_agree']['value'] != 20;
  319. }
  320. }