OrderService.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. <?php
  2. namespace App\Services;
  3. use App\Services\BaseService;
  4. use App\Services\UserService;
  5. use App\Services\ProductService;
  6. use App\Models\Order;
  7. use Illuminate\Support\Str;
  8. use Illuminate\Support\Facades\DB;
  9. class OrderService extends BaseService
  10. {
  11. public static $MODEL= Order::class;
  12. const STATUS_YES = 1;
  13. const STATUS_NOT = 0;
  14. /**
  15. * @description: 获取查询条件
  16. * @param {array} $search 查询内容
  17. * @return {array}
  18. */
  19. public static function getWhere(array $search = []): array
  20. {
  21. $where = [];
  22. if (isset($search['id']) && $search['id'] !== '') {
  23. $where[] = ['id', '=', $search['id']];
  24. }
  25. if (isset($search['user_id']) && $search['user_id'] !== '') {
  26. $where[] = ['user_id', '=', $search['user_id']];
  27. }
  28. if (isset($search['order_no']) && $search['order_no'] !== '') {
  29. $where[] = ['order_no', '=', $search['order_no']];
  30. }
  31. if (isset($search['status']) && $search['status'] !== '') {
  32. $where[] = ['status', '=', $search['status']];
  33. }
  34. if (isset($search['order_date']) && $search['order_date'] !== '') {
  35. $where[] = ['order_date', '=', $search['order_date']];
  36. }
  37. if (isset($search['paid_date']) && $search['paid_date'] !== '') {
  38. $where[] = ['paid_date', '=', $search['paid_date']];
  39. }
  40. if (isset($search['product_id']) && $search['product_id'] !== '') {
  41. $where[] = ['product_id', '=', $search['product_id']];
  42. }
  43. return $where;
  44. }
  45. /**
  46. * @description: 查询单条数据
  47. * @param array $search
  48. * @return
  49. */
  50. public static function findOne(array $search)
  51. {
  52. return static::model()::where(static::getWhere($search))->first();
  53. }
  54. /**
  55. * @description: 查询所有数据
  56. * @param array $search
  57. * @return \Illuminate\Database\Eloquent\Collection
  58. */
  59. public static function findAll(array $search = [])
  60. {
  61. return static::model()::where(static::getWhere($search))->get();
  62. }
  63. /**
  64. * @description: 分页查询
  65. * @param array $search
  66. * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
  67. */
  68. public static function paginate(array $search = [])
  69. {
  70. $limit = isset($search['limit']) ? $search['limit'] : 15;
  71. $paginator = static::model()::where(static::getWhere($search))
  72. ->orderBy('id', 'desc')
  73. ->paginate($limit);
  74. return ['total' => $paginator->total(), 'data' => $paginator->items()];
  75. }
  76. /**
  77. * @description:
  78. * @param {*} $params
  79. * @return {*}
  80. */
  81. public static function submit($params = [])
  82. {
  83. $result = false;
  84. $msg['code'] = self::NOT;
  85. $msg['msg'] = '';
  86. // 2. 判断是否是更新
  87. if (!empty($params['id'])) {
  88. // 更新
  89. $info = self::findOne(['id'=>$params['id']] );
  90. if (!$info) {
  91. $msg['msg'] = '数据不存在!';
  92. }else{
  93. $result = $info->update($params);
  94. $id = $params['id'];
  95. }
  96. } else {
  97. // 创建
  98. $result = $info = self::model()::create($params);
  99. $id = $result->id;
  100. }
  101. if($result){
  102. $msg['code'] = self::YES;
  103. $msg['msg'] = '设置成功';
  104. }else{
  105. $msg['msg'] = empty($msg['msg']) ?'操作失败':$msg['msg'];
  106. }
  107. return $msg;
  108. }
  109. /**
  110. * @description: 分配订单
  111. * @param {*} $user_id 用户ID
  112. * @return {*}
  113. */
  114. public static function assignOrder($user_id)
  115. {
  116. $result = [];
  117. $result['code'] = self::NOT;
  118. $result['data'] = [];
  119. $today = date('Y-m-d');
  120. // // 查找个人待处理订单
  121. // $pendingOrder = self::findOne(['user_id' => $user_id,'status' => self::STATUS_NOT]);
  122. // 用户信息
  123. $userInfo = UserService::findOne(['id' => $user_id]);
  124. $balance = $userInfo->balance; // 余额
  125. $productPriceMax = config_val('product_price_max'); // 商品最高价
  126. $maxOrderQuantity = $userInfo->membership->quantity; // 用户每日可完单限制
  127. if($maxOrderQuantity > 0){
  128. // 今日完单数
  129. $todayCompleteQuantity = static::model()::where(self::getWhere(['user_id' => $user_id ,'status' => self::STATUS_YES]))->count();
  130. if($todayCompleteQuantity >= $maxOrderQuantity){
  131. if($userInfo->membership_level_code =='silver'){
  132. $result['msg'] = '恭喜您,今日订单已完成!可在升级黄金会员后继续新一轮订单';
  133. }else{
  134. $result['msg'] = '恭喜您,今日订单已完成!可在升级钻石会员后继续新一轮订单';
  135. }
  136. return $result;
  137. }
  138. }
  139. $minPrice = 0; // 最低消费
  140. // 已完成数量
  141. $completeQuantity = static::model()::where(self::getWhere(['user_id' => $user_id ,'status' => self::STATUS_YES]))->count();
  142. // 达到卡单数
  143. if(($completeQuantity + 1) == $userInfo->blocked_order){
  144. $minPrice = bcadd($balance, $userInfo->blocked_amount, 4); // 计算最低消息
  145. }
  146. $product_commission_min = config_val('product_commission_min'); // 商品佣金最低
  147. $product_commission_max = config_val('product_commission_max'); // 商品佣金最高
  148. // 已下单的商品id集合
  149. // $productIds = static::model()::where(self::getWhere(['user_id' => $user_id]))->pluck('product_id');
  150. $productIds = [];
  151. // 随机的商品信息
  152. $randomProduct = ProductService::getRandom($productIds,$balance,$minPrice);
  153. if(empty($randomProduct)){
  154. $result['msg'] = '暂无适合的商品,请稍后再试';
  155. return $result;
  156. }
  157. $productPrice = $randomProduct->price; // 商品价格
  158. if($minPrice > 0){
  159. $price = $minPrice;
  160. }else{
  161. if($balance < $productPrice){
  162. $price = bcadd($productPrice,rand(10,50),2);
  163. }else{
  164. $priceMin = bcmul($balance,0.3,2); // 最低价
  165. if($balance > 10000){
  166. $priceMin = 1000;
  167. }
  168. if($priceMin < $productPrice){
  169. $priceMin = $productPrice;
  170. }
  171. $priceMax = bcmul($balance,0.7,2); // 最高价
  172. if($priceMax < $productPrice){
  173. $priceMax = $productPrice;
  174. }
  175. if($priceMax > $productPriceMax){
  176. $priceMax = $productPriceMax;
  177. }
  178. $price = random_float($priceMin,$priceMax,4);
  179. }
  180. }
  181. $price = retain_number_format($price);
  182. $commission = bcmul($price,random_float($product_commission_min,$product_commission_max,4),4);
  183. if($minPrice > 0){
  184. $commission = $userInfo->blocked_profit; // 卡單默認佣金
  185. }
  186. $commission = retain_number_format($commission);
  187. $data = [];
  188. $data['order_no'] = self::generalOrderNo($user_id); // 订单号
  189. $data['user_id'] = $user_id; // 用户
  190. $data['product_id'] = $randomProduct->id; // 商品ID
  191. $data['price'] = $price; // 商品价格
  192. $data['commission'] = $commission; // 商品佣金
  193. $data['product_snapshot'] = json_encode($randomProduct,JSON_UNESCAPED_UNICODE); // 商品快照
  194. $data['status'] = self::STATUS_NOT; // 订单待处理
  195. $data['order_date'] = date('Y-m-d'); // 订单日期
  196. // $data['paid_date'] = date('Y-m-d'); // 完单日期
  197. $order = static::model()::create($data);
  198. if($order){
  199. $result['code'] = self::YES;
  200. $result['msg'] = '订单已生成,请尽快支付';
  201. $result['data'] = $order;
  202. }else{
  203. $result['msg'] = '分配订单失败,请稍后再试';
  204. }
  205. return $result;
  206. }
  207. // 生成随机的订单号
  208. public static function generalOrderNo($user_id = 0)
  209. {
  210. $orderNo = 'ORD' . now()->format('YmdHis') . Str::random(6).'_'.$user_id;
  211. return $orderNo;
  212. }
  213. /**
  214. * @description: 订单支付
  215. * @param {*} $orderNo 订单号
  216. * @param {*} $userId 用户ID
  217. * @return {*}
  218. */
  219. public static function paymentOrder($orderNo,$userId)
  220. {
  221. $result = [];
  222. $result['code'] = self::NOT;
  223. $orderInfo = self::findOne(['order_no' => $orderNo ,'user_id' => $userId]);
  224. if(!$orderInfo){
  225. $result['msg'] = '未找到相关订单数据';
  226. return $result;
  227. }
  228. if($orderInfo->status == self::STATUS_YES){
  229. $result['msg'] = '订单已支付,请勿重复提交';
  230. return $result;
  231. }
  232. $userInfo = UserService::findOne(['id' => $userId]);
  233. $balance = $userInfo->balance; // 余额
  234. $chaMoney = bcsub($orderInfo->price,$balance,2);
  235. if($balance < $orderInfo->price){
  236. $result['msg'] = lang('当前账户余额不足,完成此订单还差{money},请先完成充值');
  237. $result['msg'] = str_replace('{money}',$chaMoney,$result['msg']);
  238. $result['money'] = $chaMoney;
  239. return $result;
  240. }
  241. // $afterBalance = bcsub($balance,$orderInfo->price,4);
  242. if(bcsub($balance,$orderInfo->price,4) < 0){
  243. $result['msg'] = lang('当前账户余额不足,完成此订单还差{money},请先完成充值');
  244. $result['msg'] = str_replace('{money}',$chaMoney,$result['msg']);
  245. $result['money'] = $chaMoney;
  246. return $result;
  247. }
  248. // 能支付成功直接返佣
  249. $afterBalance = bcadd($balance,$orderInfo->commission,4);
  250. DB::beginTransaction();
  251. try {
  252. // 更新用户余额
  253. $userInfo->balance = $afterBalance;
  254. $userInfo->save();
  255. $orderInfo->status = self::STATUS_YES;
  256. $orderInfo->paid_date = date('Y-m-d');
  257. $orderInfo->save();
  258. // 支付
  259. $log = UserBalanceLogService::addLog(
  260. $userId,
  261. '佣金',
  262. $balance,
  263. $orderInfo->commission,
  264. '订单:'.$orderNo
  265. );
  266. // 60单发奖励
  267. if(static::model()::where(self::getWhere(['user_id' => $userId ,'status' => self::STATUS_YES]))->count() == 60){
  268. $profit = rand(config_val('bonus_min'),config_val('bonus_max'));
  269. // 一级返
  270. if($userInfo->inviter_id_1){
  271. self::inviterBonus($userInfo->inviter_id_1,$profit,$orderNo);
  272. }
  273. }
  274. if($log['code'] == self::NOT){
  275. DB::rollBack();
  276. return $log;
  277. }
  278. // // 一级返
  279. // if($userInfo->inviter_id_1){
  280. // $percentage = config_val('inviter_commission_1');
  281. // self::inviterCommission($userInfo->inviter_id_1,$orderInfo->commission,$percentage,$orderNo);
  282. // }
  283. // // 二级返
  284. // if($userInfo->inviter_id_2){
  285. // $percentage = config_val('inviter_commission_2');
  286. // self::inviterCommission($userInfo->inviter_id_2,$orderInfo->commission,$percentage,$orderNo);
  287. // }
  288. // // 三级返
  289. // if($userInfo->inviter_id_3){
  290. // $percentage = config_val('inviter_commission_3');
  291. // self::inviterCommission($userInfo->inviter_id_3,$orderInfo->commission,$percentage,$orderNo);
  292. // }
  293. DB::commit();
  294. $msg['code'] = self::YES;
  295. $msg['msg'] = '刷单成功';
  296. return $msg;
  297. } catch (\Exception $e) {
  298. DB::rollBack();
  299. $msg['msg'] = $e->getMessage();
  300. return $msg;
  301. }
  302. }
  303. /**
  304. * @description: 分佣
  305. * @param {*} $user_id 用户ID
  306. * @param {*} $amount 分佣金额
  307. * @param {*} $percentage 比例
  308. * @return {*}
  309. */
  310. public static function inviterCommission($userId, $amount, $percentage, $orderNo)
  311. {
  312. $userInfo = UserService::findOne(['id' => $userId]);
  313. if($userInfo){
  314. $balance = $userInfo->balance;
  315. // 使用高精度乘法,设置合适的精度(比如4位小数)
  316. $changeAmount = bcmul($amount, $percentage, 8); // 中间计算使用较高精度
  317. // 如果需要最终结果保留4位小数
  318. $changeAmount = bcadd($changeAmount, '0', 4);
  319. // 支付
  320. UserBalanceLogService::addLog(
  321. $userId,
  322. '分佣',
  323. $balance,
  324. $changeAmount,
  325. '订单:'.$orderNo
  326. );
  327. }
  328. }
  329. /**
  330. * @description:
  331. * @param {*} $user_id 用户ID
  332. * @param {*} $profit 奖金
  333. * @param {*} $orderNo 订单
  334. * @return {*}
  335. */
  336. public static function inviterBonus($userId, $profit, $orderNo)
  337. {
  338. $userInfo = UserService::findOne(['id' => $userId]);
  339. if($userInfo){
  340. $balance = $userInfo->balance;
  341. $changeAmount = $profit;
  342. // 支付
  343. UserBalanceLogService::addLog(
  344. $userId,
  345. '代理奖金',
  346. $balance,
  347. $changeAmount,
  348. '订单:'.$orderNo
  349. );
  350. $userInfo->balance = bcadd($balance,$profit,2);
  351. $userInfo->save();
  352. }
  353. }
  354. /**
  355. * @description: 统计订单数据
  356. * @param {*} $user_id
  357. * @return {*}
  358. */
  359. public static function statOrder($userId)
  360. {
  361. $result = [];
  362. $userInfo = UserService::findOne(['id' => $userId]);
  363. $result['balance'] = $userInfo->balance??0;
  364. $result['membership_name'] = $userInfo->membership_name??'';
  365. $result['membership_level_code'] = $userInfo->membership_level_code??'';
  366. // $result['userInfo'] = $userInfo;
  367. $today = date('Y-m-d');
  368. $yesterday = date('Y-m-d',(time() - 86400));
  369. // 总收益
  370. $result['total_profit'] = static::model()::where(self::getWhere(['user_id' => $userId ,'status' => self::STATUS_YES]))->sum('commission');
  371. // 今日收益
  372. $result['today_profit'] = static::model()::where(self::getWhere(['user_id' => $userId ,'status' => self::STATUS_YES ,'order_date' => $today]))->sum('commission');
  373. // 昨日收益
  374. $result['yesterday_profit'] = static::model()::where(self::getWhere(['user_id' => $userId ,'status' => self::STATUS_YES ,'order_date' => $yesterday]))->sum('commission');
  375. // 总单数
  376. $result['total_count'] = static::model()::where(self::getWhere(['user_id' => $userId ,'status' => self::STATUS_YES]))->count();
  377. // 未完成
  378. $result['total_pending_count'] = static::model()::where(self::getWhere(['user_id' => $userId ,'status' => self::STATUS_NOT]))->count();
  379. // 今日单数
  380. $result['today_count'] = static::model()::where(self::getWhere(['user_id' => $userId ,'status' => self::STATUS_YES ,'order_date' => $today]))->count();
  381. // 昨日单数
  382. $result['yesterday_count'] = static::model()::where(self::getWhere(['user_id' => $userId ,'status' => self::STATUS_YES ,'order_date' => $yesterday]))->count();
  383. return $result;
  384. }
  385. }